Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
507 views
in Technique[技术] by (71.8m points)

c++ - Can't read .dat or .bin file in Ubuntu "Segmentation fault (core dumped)"

So, I just started using Ubuntu recently. I'm building this very simple program that will let me store some data and read back from it later on.

Using C++, fstream, some objects are stored in .dat file.

// function to store
void storeRecord(Record r){
     fstream afile;
     afile.open("file.dat" , ios::out | ios::binary | ios::app);
     afile.write(reinterpret_cast <const char*> (&r), sizeof(r) );
     afile.close();
}

But when I try to (call query() function) read from the same file, I'm getting "Segmentation fault (core dumped)"

void query(){
        Record r;
        fstream afile;
        afile.open("file.dat", ios::in | ios::binary);
        while(afile.read(reinterpret_cast <char*> (&r), sizeof(r))){
             // do something
        }
        afile.close();
}

This used to work on windows. Why is that?

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

class Record{
public:
    // Constructors
    Record();
    Record(string accountID, string name, string deptID, string password,           int role);
    ~Record();

    // Assessors and Mutators
    string getAccountID();
    string getName();
    string getDeptID();
    string getPW();
    int getRole();

    void setAccountID(string accountID);
    void setName(string name);
    void setDeptID(string deptID);
    void setPW(string PW);
    void setRole(int role);

    // Other functions
    string toString();

private:
    string accountID;
    string name;
    string deptID;
    string password;
    int role;       // normal user, HR personal, admin
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your Record contains std::string fields.

A string certainly contains pointers, and could contain some internal data with virtual functions (so having a vtable, which is a hidden pointer); then that data has pointers. And a string is not a POD (but a fixed array of char would be, e.g. a field like char name[48]; ....).

So your code has undefined behavior so you are lucky that it crashes on Linux (and unlucky that it "appears" to work on Windows)... BTW, when it is apparently "running" (e.g. on your Windows) the file format stays "undefined" and you won't be able to read again a data file written by an older version of your program (or even the same source compiled by an older or different compiler and C++ standard library).

Linux has ASLR; that might explain why you've got a segmentation fault. BTW, I guess that Linux might not crash if you write and read the same data file in the same process (which is not particularly useful to you).

To understand more, you'll have to dive into implementation details, and you don't want to.

Apparently, you are required to implement some serialization machinery. Then specify first (and in details) your file format (byte by byte, endianness and "word size" matter and your file format should be "independent" of them), perhaps using some EBNF notation. Then implement the serialization routines, starting from elementary POD types. Or use some serialization library. Your file format and code should be portable (e.g. the same program on Raspberry Pi and on Linux/PC should be able to exchange data files).

BTW, I prefer much using some textual format, perhaps using JSON, YAML (or XML). Or consider also libraries like SQLite or GDBM. In your case, your Records map easily to rows in SQLite tables, or to JSON objects. Perhaps you should ask your teacher if you are allowed to use them....


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...