   C++ std::string in struct causes error in RtlValidateHeap
  Hi,I am trying to read in a simple struct from a binary file. However, I get an error saying "Debug Assertion Failed!" It tells me this is in dbgdel.cpp, and the expression is: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)In the output window (VS 2003 .NET) it prints:HEAP[LevelEditor.exe]: Invalid Address specified to RtlValidateHeap( 01510000, 01512650 )The problem seems to occur because of a std::string in the struct I am trying to read -- the problem goes away without it. It breaks on the closing bracket of the read loop. Below is the read code:// Fill a temporary vector with spawn structs.std::vector<SpawnStruct> spawnStructs;for (int i = 0; i < numSpawns; i++)}SpawnStruct toAdd;file.read((char*)(&toAdd), sizeof(SpawnStruct));spawnStructs.push_back(toAdd);}Below is the struct definition:struct SpawnStruct{int sType;int sWidth;int sHeight;D3DXVECTOR3 sLocation;std::string sImagePath;D3DXVECTOR3 sCenter;};The call stack includes this line...LevelEditor.exe!<Module>.SpawnStruct::~SpawnStruct() + 0xf bytes...and then goes into things involving strings, "operator delete," and "_free_dbg".From google I gather that this can be caused by trying to delete something twice, or running DLL's, neither of which I think I'm doing.Any help or hints on what to look for would be greatly appreciated!   
  There is some pointer in the string that is valid in the context it has been saved, but not where it is loaded. I might argue you do something like:struct mystruct {int * p;// other args}mystruct s;void first_run() {s.p = new int[10];save(s);}void second_run() {load(s); delete [] s.p; // error since// s.p points to the memory of the other program (if absolute)// or in an invalid point (if relative)}   ;  The problem is that std::string itself doesn't store any character data in the class. It might, for example, contain nothing more than 3 pointers pointing to different portions of memory.So when you stream a std::string to file, all you're copying to file are 3 pointers which point to some position in memory. When you grab that back from file again, what you have are a bunch of invalid pointers, nothing more.The solution to this is to use c-style strings or pascal-style strings.   ;Quote:Original post by Sc4FreakThe solution to this is to use c-style strings or pascal-style strings.Clearly using a fire to heat a home is incompatible with living in a cave, what the problem with smoke and all. Who cares about that "fireplace" thing? Let's stop using fire!The problem here comes not from the usage of C++ strings (which, in itself, is sensible and efficient) but rather from the practice of doing file I/O by copying raw bytes between a buffer and a file—something which both C++ programs and any remotely portable C program will shun—which will break on any non-POD (including std::string, the reason why the program dies in   this example) but will also cause portability problems on anything other than a   char or an array thereof. Even if he did revert to using C or   pascal strings, his levels would still be unusable on a 64-bit platform because the structure contains three int members (or, if he uses the editor on a 64-bit platform, 32-bit users won't be able to read levels). As a rule of thumb, if an I/O operation contains the keyword sizeof, you have a problem. A correct approach to the problem, in both C and C++, would be to write serialization and deserialization functions for the structure and its members (or to reuse an existing system, such as boost::serialize, which already handles most of C++).For example, using the boost approach: namespace boost {  namespace serialization   {    template<class Archive>    void serialize(Archive & ar, D3DXVector3 & v, const unsigned int version)    { ar & v.x; ar & v.y; ar & v.z;    }  } } struct SpawnStruct{  Int32 type;  Int32 width;  Int32 height;  D3DXVECTOR3 location;  std::string imagePath;  D3DXVECTOR3 center;  template<class Archive>  void serialize(Archive & ar, const unsigned int version)  {    ar & type;    ar & width;    ar & height;    ar & location;    ar & imagePath;    ar & center;  }};// Fill a vector and write it to 'file'std::vector<SpawnStruct> spawnStructs;boost::archive::binary_oarchive ar(file);ar & spawnStructs;