0

I'm trying to read and write to a binary file, it mostly works however

upon returning 0 in main ill get munmap_chunk(): invalid pointer: error

ill get a memory dump and a stack trace when the program closes

https://i.stack.imgur.com/UaCtk.jpg

here is a screenshot of the memory dump and stack trace, I don't know how to read this

#include <fstream>
#include <iostream>

using namespace std; 

struct player{
  string name;
};

   bool WriteTest(player playerData){
  // Create our objects.
  fstream filestream;
  //attempt to open file and then read first player
  filestream.open ("file.bin", ios::binary | ios::out);
  filestream.write(reinterpret_cast <char *> (&playerData), 
sizeof(playerData));
       if(filestream.fail()){
    //create file if there is no file
    cout << "write open failed" << endl;
    filestream.close();
    return false;
  }
    filestream.close();
        cout << "write sucsess" << endl;
          return true;
}

player ReadTest(){
  player playerData;
  // Create our objects.
  fstream filestream;
  //attempt to open file and then read first player
  filestream.open ("file.bin", ios::binary | ios::in);
  filestream.read(reinterpret_cast <char *> (&playerData), 
sizeof(playerData));
  if(filestream.fail()){
    //create file if there is no file
    cout << "read open failed" << endl;
    filestream.close();
    return playerData;
  }
  filestream.close();
  cout << "read sucsess" << endl;
  return playerData;
}

void displayPlayerData(player playerData){
  cout << " Name :" << playerData.name << endl;
}

int main(){
  player source;
  source.name = "bap";
  displayPlayerData(source);
  WriteTest(source);
 getchar();
  player playerData = ReadTest();
  displayPlayerData(playerData);
  return 0;
}
  • 1
    `filestream.read(reinterpret_cast (&playerData), sizeof(playerData));` -- This line will never work. `playerData` is a non-POD type, thus you cannot read or write those types in this fashion. Learn about proper object serialization. – PaulMcKenzie Mar 15 '18 at 04:39
  • [More reading on object serialization](https://stackoverflow.com/questions/28816037/object-serialization-in-c). I almost want to close this as a duplicate, since I see so many questions with the same error -- trying to do erroneous binary reading and writing of non-POD types. – PaulMcKenzie Mar 15 '18 at 04:45
  • I don't understand that post, it seems to be telling me to write a static function in the struct but i don't know how to use it – SpeedrunnerG55 Mar 15 '18 at 05:10
  • [Read the accepted answer here](https://stackoverflow.com/questions/7742361/c-writing-an-object-to-a-file-then-later-reading-it-in). Your code will not work, period. If you don't understand, read my answer. – PaulMcKenzie Mar 15 '18 at 05:11

1 Answers1

0

Your player struct contains a std::string, thus the type is not C-layout compatible.

Thus using functions such as:

filestream.write(reinterpret_cast <char *> (&playerData), sizeof(playerData));

and

filestream.read(reinterpret_cast <char *> (&playerData), sizeof(playerData));

will not work correctly.

The std::string contains a pointer to a buffer of characters (leaving aside the short string buffer if the string class is implemented that way), and writing std::string directly to a file will totally miss those characters since you will only be writing a pointer value.

Additionally, reading into playerData will not initialize the std::string with the data. Instead you'll just be corrupting the std::string object with garbage you read from the file. This is more than likely where your program fails -- you are trying to use a corrupted std::string object.

But the tell-tale sign why this could never work is that sizeof(player) is a fixed, compile-time value, and it is the third parameter in the read and write functions. When run here, the sizeof(player) is 32. So you will always be reading / writing 32 bytes of data. What if the std::string name; member holds 1,000 characters? How will you be able to read/write 1,000 characters by specifying you only want to read/write 32 bytes? That could never work.

The correct way to handle this is either:

1) Change the std::string member to an array of char. Then the player class will be C-layout compatible and can be read and written using your techniques of binary file reading / writing

or

2) Properly serialize the string data to the file. You can overload operator >> and operator << to read/write the string data, or use a library such as Boost::Serialize.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45