0
votes

Attempting to write a data struct containing vector members, I noticed that vector members were not accurate when the data was being read back from the buffer.

First I write out the structure manually with simple values: (Assume POD members are accurate in this case.)

void ObjFileImport::WriteGeometryFile(LPWSTR In_File){
BaseGeometry WriteTest;
WriteTest.VertexData = {
    XMFLOAT3(9.5, 6.7f, 9.3f),
    XMFLOAT3(3.5f, 6.7f, 9.3f),
    XMFLOAT3(3.5f, 6.7f, 9.3f) };
WriteTest.ColorData = { XMFLOAT4(3.5f, 6.7f, 9.3f, 5.6f) };
WriteTest.Update();

ofstream File;
File.open(In_File, ofstream::binary | ofstream::out);

if (File.is_open()){
    File.write((const char*)&WriteTest.Version, sizeof(float));

    File.write((const char*)&WriteTest.sz_Array[0], sizeof(size_t)*WriteTest.sz_BG_Mbr); 

    File.write((const char*)WriteTest.ColorData.data(),         sizeof(XMFLOAT4)*WriteTest.sz_ColorData);
    File.write((const char*)WriteTest.ImageData.data(),         sizeof(XMFLOAT4)*WriteTest.sz_ImageData);
    File.write((const char*)WriteTest.VertexData.data(),        sizeof(XMFLOAT3)*WriteTest.sz_VertexData);
    File.write((const char*)WriteTest.NormalData.data(),        sizeof(XMFLOAT3)*WriteTest.sz_NormalData);
    File.write((const char*)WriteTest.TextureCoordData.data(),  sizeof(XMFLOAT2)*WriteTest.sz_TextureCoordData);

    File.write((const char*)&WriteTest.IndexVertexData,         sizeof(UINT)*WriteTest.sz_IndexVertexData);
    File.write((const char*)&WriteTest.IndexTextureCoordData,   sizeof(UINT)*WriteTest.sz_IndexTextureCoordData);
    File.write((const char*)&WriteTest.IndexNormalData,         sizeof(UINT)*WriteTest.sz_IndexNormalData);
}
File.close();
}

This works fine... according to the regular types showing up on read, which looks like:

void ObjFileImport::ReadGeometryFile(LPWSTR In_File){
int Sz_Base = sizeof(BaseGeometry);
BaseGeometry Temp;
ifstream File;
File.open(In_File, ifstream::binary | ifstream::in | ifstream::ate);

if (File.is_open()){ 
    int FileSize = File.tellg();
    File.seekg(0, File.beg);

    //Read version number.
    File.read((char*)&Temp.Version, sizeof(float));

    File.read((char*)&Temp.sz_Array, sizeof(size_t)           *Temp.sz_BG_Mbr); //Test for heap tranfer

    File.read((char*)&Temp.ColorData, sizeof(XMFLOAT4)        *Temp.sz_ColorData);
    File.read((char*)&Temp.ImageData, sizeof(XMFLOAT4)        *Temp.sz_ImageData);
    File.read((char*)&Temp.VertexData, sizeof(XMFLOAT3)       *Temp.sz_VertexData);
    File.read((char*)&Temp.NormalData, sizeof(XMFLOAT3)       *Temp.sz_NormalData);
    File.read((char*)&Temp.TextureCoordData, sizeof(XMFLOAT2) *Temp.sz_TextureCoordData);

    File.read((char*)&Temp.IndexVertexData, sizeof(UINT)      *Temp.sz_IndexVertexData);
    File.read((char*)&Temp.IndexTextureCoordData, sizeof(UINT)*Temp.sz_IndexTextureCoordData);
    File.read((char*)&Temp.IndexNormalData, sizeof(UINT)      *Temp.sz_IndexNormalData);

    File.close();
}
}

Unfortunately, while reading from the data buffer, the vector values (and size) are not showing up.

VS runtime values I know that vector essentially points to data stored on the heap and tried to get the internal pointer for that data WriteTest.data() to read into the binary file. Upon reading out, the data doesn't seem to be structured intuitively.

2
Like you say, a vector contains a pointer to the heap-allocated data, and all heap-allocations (and, really, all pointers) are unique to the current process. If you save a pointer to allocated data, and then read it in another program (or even the same program but as a new process) then that pointer no longer points to allocated memory. You should search for and read about serialization. There are many good libraries to handle serialization for you, use them. - Some programmer dude
If all of this stuff is a std::vector, why are there separate variables that indicate the size of each vector? Do you know about std::vecto::size()? And, when reading the data back, "File.read((char*)&Temp.ColorData," completely overwrites and scribbles over the std::vector itself, instead of its data(), and it is also your responsibility, upon reading, to size the std::vector so it contains sufficient elements, before reading the data into the std::vector's data(). - Sam Varshavchik
Is there a way to reference the heap data directly - to copy to the file? - Rashid Ellis
Is there a way to reference the heap data directly - to copy to the file? No when it contains pointers you can not do that. Also the heap need not be contiguous and the objects you put on the heap need not be in any specific order. So you would get garbage back. - drescherjm
You can access row data of vector by &v[0] stackoverflow.com/questions/6485496/… - VladimirS

2 Answers

1
votes

C++ STL does not provide native interface to store STL object to disk.

You can check this thread for help.

0
votes

For this implementation, (As noted by Sam Varshavchik, comments) vector objects were being overwritten and [as well], the relevant data pointed to by the vector's internal pointer, when referenced, returned an assert error, due to not being sized correctly for the data being forced in.

void ObjFileImport::ReadGeometryFile(LPWSTR In_File){
int Sz_Base = sizeof(BaseGeometry);
BaseGeometry Temp;
ifstream File;
File.open(In_File, ifstream::binary | ifstream::in | ifstream::ate);

if (File.is_open()){ 
    int FileSize = File.tellg();
    File.seekg(0, File.beg);

    //Read version number.
    File.read((char*)&Temp.Version, sizeof(float));

    //Brace for horrible things later. Read size definition array.
    File.read((char*)&Temp.sz_Array, sizeof(size_t)*Temp.sz_BG_Mbr); 

    //If local pointer null, make not null, else, allocate space.
    if (Temp.sz_ColorData == 0)Temp.ColorData.resize(1);
    else Temp.ColorData.resize(Temp.sz_ColorData);

    if (Temp.sz_ImageData == 0)Temp.ImageData.resize(1);
    else Temp.ImageData.resize(Temp.sz_ImageData);

    if (Temp.sz_VertexData == 0)Temp.VertexData.resize(1);
    else Temp.VertexData.resize(Temp.sz_VertexData);

    if (Temp.sz_TextureCoordData == 0)Temp.TextureCoordData.resize(1);
    else Temp.TextureCoordData.resize(Temp.sz_TextureCoordData);

    if (Temp.sz_NormalData == 0)Temp.NormalData.resize(1);
    else Temp.NormalData.resize(Temp.sz_NormalData);

    if (Temp.sz_IndexVertexData == 0)Temp.IndexVertexData.resize(1);
    else Temp.IndexVertexData.resize(Temp.sz_IndexVertexData);

    if (Temp.sz_IndexTextureCoordData == 0)Temp.IndexTextureCoordData.resize(1);
    else Temp.IndexTextureCoordData.resize(Temp.sz_IndexTextureCoordData);

    if (Temp.sz_IndexNormalData == 0)Temp.IndexNormalData.resize(1);
    else Temp.IndexNormalData.resize(Temp.sz_IndexNormalData);

    //Read contents of buffer in.
    File.read((char*)Temp.ColorData.data(), sizeof(XMFLOAT4)          *Temp.sz_ColorData);       // *Temp.sz_ColorData);
    File.read((char*)Temp.ImageData.data(), sizeof(XMFLOAT4)          *Temp.sz_ImageData);
    File.read((char*)Temp.VertexData.data(), sizeof(XMFLOAT3)         *Temp.sz_VertexData);
    File.read((char*)Temp.NormalData.data(), sizeof(XMFLOAT3)         *Temp.sz_NormalData);
    File.read((char*)Temp.TextureCoordData.data(),   sizeof(XMFLOAT2) *Temp.sz_TextureCoordData);

    File.read((char*)Temp.IndexVertexData.data(),   sizeof(UINT)      *Temp.sz_IndexVertexData);
    File.read((char*)Temp.IndexTextureCoordData.data(),   sizeof(UINT)*Temp.sz_IndexTextureCoordData);
    File.read((char*)Temp.IndexNormalData.data(),    sizeof(UINT)     *Temp.sz_IndexNormalData);

    File.close();
}
}  

The "Fixed" code, although whether the data "persists" across machine types may be up for question.