Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialization of complex structures in C++

Tags:

c++

struct

I'm trying to serialize a set of structs in C++. This works great for all data except a vector contained in my struct. I can write the data to disk, and then read all data back into memory. The only problem is when I try to access an element of the vector I get a segmentation fault. My code is below. Any help is greatly appreciated.

Program to write to disk

int main {
  struct Student one;
  strcpy(one.FullName, "Ernestine Waller");
  strcpy(one.CompleteAddress, "824 Larson Drv, Silver Spring, MD 20910");
  one.Gender = 'F';
  one.LivesInASingleParentHome = true;
  one.grades.push_back(80);
  one.grades.push_back(90);

  ofstream ofs("fifthgrade.ros", ios::binary);
  ofs.write((char *)&one, sizeof(one));
  ofs.close();
}

Program to read from disk

 int main {
    struct Student *two = (struct Student *) malloc(sizeof(struct Student));    
    ifstream ifs("fifthgrade.ros", ios::binary);
    //cout << "Size of struct: " << size << endl;
    ifs.read((char *)two, sizeof(struct Student));
    cout << "Student Name: " << two->FullName << endl;
    cout << "First Grade: " <<  two->grades[0] << endl;
    cout << "Second Grade: " << two->grades[1] << endl;
    ifs.close();
    return 0;
 }
like image 709
Dan Avatar asked Aug 19 '10 16:08

Dan


2 Answers

What you are doing is taking copying a contiguous region of memory in which you have stored one and wrote it to disk. This will work fine for simple data types (POD in C++ jargan). The problem with vectors is that a vector is a complex object with pointers to other regions of memory. These other regions of memory don't exist when you de-serialize one into two hence your segmentation fault.

Unfortunately there is no shortcut, some form on custom serialization code will need to be written to get the job done.

As some have already mentioned Boost Serialization may help. Alternatively roll out your own.

like image 130
doron Avatar answered Oct 22 '22 14:10

doron


Probably the simplest version of serializing a vector that stands a chance of working is something like:

your_stream << your_vector.size();
std::copy(your_vector.begin(), your_vector.end(),
     std::ostream_iterator<your_vector::value_type>(your_stream, "\n"));

Reading it back goes something like:

size_t size;
your_stream >> size;
vector_two.resize(size);
for (size_t i=0; i<size; i++)
    your_stream >> vector_two[i];

Note that this is not particularly efficient -- in particular, it (basically) assumes the data will be stored in text format, which is often fairly slow and takes up extra space (but is easy to read, manipulate, etc., by outside programs, which is often useful).

like image 22
Jerry Coffin Avatar answered Oct 22 '22 15:10

Jerry Coffin