-6

Note: While I was debugging, I found that until the last line, the program run normally, but when going by the last bracket, a mistake window would pop up. I'm not quite familiar with C++ so I couldn't locate the problem. Please help!

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
class test {
    public:
        int x;
        void add_list(int);
        void display();
    private:
        vector<int> list;
};
void test::add_list(int op)
{
    list.push_back(op);
}
void test::display()
{
    cout << x << endl;
    for (unsigned int i=0;i<list.size(); i++)
    cout << "->" << list[i];
    cout << endl;
}
int main (void)
{
    test test1;
    test1.x = 3;
    test1.add_list(2);
    test1.add_list(4);
    int size = sizeof (test1);
    ofstream fout ("data.dat", ios_base::binary);
    fout.write((char *)&test1, size);
    fout.close();
    ifstream fin ("data.dat", ios_base::binary);
    test test2;
    fin.read((char *)&test2, size);
    test2.display();
    fin.close();
    return 0;
}
  • 2
    What does the error say? – SteveFerg Jul 11 '15 at 04:00
  • We need to know what the error is to help. – celticminstrel Jul 11 '15 at 04:05
  • 4
    @HaroldHuang Reading and writing non-POD types like this will not work properly. You cannot save or read these types using binary mode. The object has to be properly serialized. – PaulMcKenzie Jul 11 '15 at 04:06
  • 0xC0000005: when writing into 0xFEEEFEEE , conflict happens. – Harold Huang Jul 11 '15 at 04:06
  • @HaroldHuang More than likely, the reason for the error is that you stomped all over your object by writing junk to it in the `read` call. Read my previous comment. – PaulMcKenzie Jul 11 '15 at 04:09
  • @PaulMcKenzie Then what do I have to do to make it work? How to serialize the object? I'm quite new to C++... – Harold Huang Jul 11 '15 at 04:15
  • @HaroldHuang You write the *data* to a file, not the raw object bytes (which is what you are doing). The same thing with the `read`. For example, you should write the `int` member, then you write the `vector` data, one item at a time to the file. What your `read` is doing is taking an object `test2` that is already constructed, and ripping it to shreds by writing over its internals with junk. That is the layman's way of explaining it. – PaulMcKenzie Jul 11 '15 at 04:19
  • @HaroldHuang Having said all of that, where did you get the idea to save data like this, using binary mode? You are not the first to do this mistake, and I see it done too often here on SO and elsewhere. Is this method actually being taught somewhere? – PaulMcKenzie Jul 11 '15 at 04:22
  • @PaulMcKenzie Oh, I understand your meaning, finally. Thanks a million! (And forgive my being silly...) – Harold Huang Jul 11 '15 at 04:27
  • Another note: The immediate compilation fail I see is `void main (void)` main should return `int`. – user4581301 Jul 11 '15 at 04:30
  • 0xFEEEFEEE is a magic debugging code. It marks freed heap memory: http://stackoverflow.com/a/127404/487892 – drescherjm Jul 11 '15 at 04:48

1 Answers1

2

These lines

fout.write((char *)&test1, size);

and

fin.read((char *)&test2, size);

won't work because the test class contains objects that contain pointers. std::list will allocated extra memory using new to store items that are pushed on to it. It will then keep pointers to those items. When you write the object to disk, it will still contain those pointers to memory. When you load the object back again, the pointers will contain the same value, but your program may not have the same memory allocated and certainly won't have it allocated for the object.

In your case test2 appears to work because its internal pointers end up being the same as test1, however when you program finishes, the test1 destructor releases the memory that it allocated, then the test2 destructor tries to release the same memory, leading to your error.

To fix it, you should change your code to write the object in a defined format that doesn't use pointers (e.g. write out the item count followed by each items integer value). Then read them in the same way. One simple fwrite won't be able to do it.

The Dark
  • 8,453
  • 1
  • 16
  • 19
  • I think that `test1` is ok, even after the `write`. Yes, the `write` statement won't work, but the only harm is that the file will contain junk. The problem is with the second line in the `read`. That is where there is a problem, since a constructed object is being corrupted. – PaulMcKenzie Jul 11 '15 at 04:26
  • @PaulMcKenzie yes, definitely. That was what I was trying to say, just all those words got in my way :) – The Dark Jul 11 '15 at 04:29