Crash after loading data from binary file

Hi everybody!,

While i am continuing my learning of C++ i have to write a program to load some "employees" objects into a vector and after that save the data into a binary file. I almost complete the program, i can create the objects, include them in a vector and save them to disk, but after load them again and try show the data on the screen the program crashes. And i don´t understand why. I have read a lot of post of this forum and i know the reason of the crash is just in front of my eyes, but i am not being able to see it. The "employee" class has 3 sub-classes which inherit from it. None of which has complex data, just char arrays for names and surnames, and booleans and floats. This is the code of the function i use (which is "borrowed" from this thread http://www.cplusplus.com/forum/beginner/123220/ , thanks JLBorges for that !! ;))
1
2
3
4
5
6
7
8
9
10
11
vector<Employee*> readBinaryFile(const char* binaryFile)
{
    vector<Employee*> temporal;
    ifstream loadData(binaryFile, ios::binary);
    Employee* temp;
    while(loadData.read( reinterpret_cast<const char*>&temp, sizeof(temp)))
        temporal.push_back(temp);

    return temporal;
} 

Data is successfully loaded but the program crashes when trying to display the data. Could somebody help me please ?
Thanks a lot in advance!.

Ik.
It looks like the problem is here: Employee*

Rather than loading Employee objects, the code is loading pointers to objects. The memory locations pointed to almost certainly don't contain valid Employee objects.

I suggest you'd need to go back a step and modify the code which writes the data to the binary file, so that it saves the actual objects, not just pointers, and modify the above code in the same way.
Thanks for the quick answer Chervil :).

But after load the data i use another pointer to display it :
1
2
3
4
5
6
7
8

employees = readBinaryFile("Data_Base.dat");

for(Employee* temp : employees)
{
      temp->ShowData();
}


Is not enough to read the pointers to "Employee" objects loaded from the file ?.


Perhaps look at it this way:
 
    cout << "Size of Employee* " << sizeof(Employee*) << '\n';

The size of of the pointer will usually be either 4 or 8 bytes (32 or 64-bit system). The size of the binary file will reflect that. On the other hand, how many bytes do the char arrays for names and surnames, and booleans and floats require?

The file does not contain enough information. All it has is a record of the transient memory locations used at some point in time. Between the time of saving the file and reloading it, that memory may have been reused by countless other processes, there's no knowing what will reside there.
The biggest char array has 4 bytes size. And the size of Employee* is 4 bytes as well.

I have modified the code (which is basically the same but without pointers and with "normal loops" ) to write and read objects instead of pointers to objects and now the program is not crashing but is loading only 1 employee to the vector each time. Probably is something related to the fact that i had to convert the pure-virtual functions of the base class "Employee" to just virtual and implement the virtual destructor in a separate .cpp file rather than have it only in the .h file. because the compiler complained about instantiate an object of an abstract class:
1
2
3
4
5
6
7
8
9
10
vector<Employee> readBinaryFile(const char* binaryFile)
{
    vector<Employee> temporal;
    ifstream loadData(binaryFile, ios::binary);
    Employee temp; --> (Not possible, abstract class)
    while(loadData.read( reinterpret_cast<const char*>&temp, sizeof(temp)))
        temporal.push_back(temp);

    return temporal;
} 

Any ideas ?.
Last edited on
You don't want a vector of Employee objects. You want pointers to Employee objects, which can also point to objects of an subclass of Employee. An Employee object can never be or behave like anything but an Employee object.

You should begin with the writing of objects to file, not the reading of objects from files. Doing so will make the reading become clearer. Keep in mind that when you're writing objects of multiple types to a file, you must store enough information in the file (or the implicit format of the file) to know what type you're going to be reading from the file (and how much of the data in the file is associated with that type.)

Reading from that file requires constructing a new object of the correct type and extracting the appropriate amount of data from the file.
Hi cire!, and thanks for the advice.

Yes, i began with the writing of objects to file. This is the code of the function :
1
2
3
4
5
6
void SaveBinaryData(const char* binaryFile, const vector<Employee*> employees)
{
    ofstream saveData(binaryFile, ios::binary);
    for(const Employee * emp : employees)
        saveData.write(reinterpret_cast<char*>(&emp), sizeof(emp));
}


(By the way this function is also "inspired" in the one JLBorges wrote in the thread i mentioned before http://www.cplusplus.com/forum/beginner/123220/ , thanks again to him ! :) ).

I´ve tried also to use ios::ate in the reading function in case the problem was not to start reading the file from the back to the front but still getting the same crash.
I know i am very close to do it, but i can not see the bug... (probably i am the bug ;))
Last edited on
You are writing pointer values to the file, not the objects pointed to.

It occurs to me that if you have base class pointers and virtual functions, then you are not dealing with a trivial data type and using read/write on those objects as a whole will result in undefined behavior. The 'inspiration' for you does not involve different types stored in the same file.


I know i am very close to do it, but i can not see the bug... (probably i am the bug ;))

I don't think you're nearly as close as you think you are.

Now i see what you mean. Employee class has no pointers...at least written for me, but, because of the virtual functions, they exist in the virtual table right?. And i guess saving and reading objects of a class which contains virtual tables is far more complex than i thought when i was with text files. And i see now also that if i am writing pointers instead of objects, when i try to dereference them to see the data they are pointing the program crashes because they are pointing to nothing, is that correct ?.
So you are right, i thought i was close !. I suppose i have bitten more than i can chew but i don´t want to surrender so easy. Is there a way to avoid this disadvantages of inheritance? . Serialization and Boost libraries are going to be a bit science-fiction for a beginner aren´t they?.
Last edited on
Topic archived. No new replies allowed.