Binary IO with Objects and Vectors
I'm getting weird run-time errors from Netbeans with the following code:
Code:
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
class Data {
private:
double value;
vector<int> listOfInts;
public:
Data(double);
void Insert(int);
void ShowVector();
double GetValue(){ return value; }
};
Data::Data(double v)
{
value = v;
}
void Data::Insert(int i)
{
listOfInts.push_back(i);
}
void Data::ShowVector()
{
vector<int>::iterator it;
for(it = listOfInts.begin(); it != listOfInts.end(); it++){
cout << (*it);
}
cout << endl;
}
bool load(Data *d)
{
ifstream fin("test.bin", ios_base::in | ios_base::binary);
if (!fin.is_open()){ return false; }
fin.read((char*)(d), sizeof(Data));
fin.close();
return true;
}
bool save(Data *d)
{
ofstream fout("test.bin", ios_base::out | ios_base::binary | ios_base::trunc);
if (!fout.is_open()){ return false; }
fout.write((const char*)(d), sizeof(Data));
fout.close();
return true;
}
int main() {
Data x(4.5);
Data *y = new Data(7.8);
cout << x.GetValue() << endl;
x.Insert(1);
x.Insert(2);
x.Insert(3);
x.Insert(4);
save(&x);
cout << y->GetValue() << endl << "Vector : ";
y->ShowVector();
load(y);
cout << y->GetValue() << endl << "Vector : ";
y->ShowVector();
delete y;
return 0;
}
/cygdrive/d/Program Files/NetBeans 6.1/cnd2/bin/dorun.sh: line 103: 2132 Aborted (core dumped) "$pgm" "$@"
My actual project (far too much code to post here), which uses several vectors, one of which is of pointers to abstract classes, complains even more at run-time with the following:
handle_exceptions: Error while dumping state (probably corrupted stack)
/cygdrive/d/Program Files/NetBeans 6.1/cnd2/bin/dorun.sh: line 103: 2128 Segmentation fault (core dumped) "$pgm" "$@"
Is this a cygwin issue, my OS (Win2k) or something code related?
Re: Binary IO with Objects and Vectors
Serializing vector in this manner does not let you store elements contained by it. All you do is writing an internal pointer to elements, and when you load an object from a file, you load this pointer value, which may lead anywhere into memory, but very unlikely into place where elements are stored. you need to serialize/deserialize contents of vector manually, or use some other solutions, like Boost.Serialization.
Cheers
Re: Binary IO with Objects and Vectors
Quote:
Originally Posted by Ceramic Weasel
I'm getting weird run-time errors from Netbeans with the following code:
As Hobson pointed out, you do not write serialized data this way.
If you take a look at the file you are writing in a binary editor, do you see any of your data there? Of course not, all you see mostly is junk. So don't expect things to correctly happen when trying to read back junk data. Garbage in, garbage out (or in this case, garbage out, garbage in).
The proper way to store items is to actually store the item. If it's a string, the whole string must be stored, if it's an object that contains a person's name and address, then the name and address must be stored, etc. You can't do that by storing meaningless pointer values. To do this, you must use proper object serialization.
Regards,
Paul McKenzie
Re: Binary IO with Objects and Vectors
ios_base::binary can be quite confusing and I know I was caught out at first. I also expected that if I set the stream to binary it would put the numbers in in a binary format. I also thought the API was bad because it didn't support binary streaming.
Now whilst it may be true that being able to stream numbers in binary format then read them back in the same format can be useful, the same isn't true for whole objects. Not even POD structs unless you can be certain that the alignment will match. Even for numbers there can be endian issues across platforms (although an API might support a single endian streaming variety).
If you stream pointers into a file these values are useful only during the lifetime of the pointer in memory. Now it's not totally useless as you may be using a file as temporary storage during the program lifetime, but the file will be pretty useless once the program terminates (or the memory is freed).
Objects like std::vector will contain pointers and writing them byte-by-byte into a file then reading them back will be useless.
The way to write one of these is either:
- Using delimited text
or
- Writing a header section followed by a sequence of records.
Delimited text, for most purposes, can be the simpler to code, although the header and binary sequence of records could be both faster and more compact in file-space use.
Re: Binary IO with Objects and Vectors
Quote:
Originally Posted by NMTop40
The way to write one of these is either:
- Using delimited text
or
- Writing a header section followed by a sequence of records.
Delimited text, for most purposes, can be the simpler to code, although the header and binary sequence of records could be both faster and more compact in file-space use.
Gah, so what's the best way to do this with a vector of pointers to abstract objects? I'd need to output some sort of typeid for each one so I know what I'm looking at before reading it back in.
Re: Binary IO with Objects and Vectors
Yup, that's more or less it.
A tip: If you use only a single byte to distinguish between several different derived types of a single base class, you can use fungetc() or the iostream equivalent to put that byte back in the stream after you read it. The unget functionality is only guaranteed to work for one byte, though.
The advantage here is that each derived type can have a complete read() function which always works regardless of what's called before; *and* a higher-level read() function can peek ahead to see which of the derived types' read() functions to call next, simultaneously.
Re: Binary IO with Objects and Vectors
How to serialize in C++.
I looking for non-binary data type first then binary.
Thanks for your help.