Reputation: 33
I have started to learn C++ some weeks ago and now I have a problem with my current project.
I wanted to write templates, that allow me to save objects into binary datas and load them again later. Here ist the code of these templates:
#ifndef TOOLS_H
#define TOOLS_H
#include <fstream>
#include <string>
namespace Tools
{
template <class T>
void writeBinaryFile(std::string filename, T object)
{
std::ofstream of(filename, std::ios::out | std::ios::binary);
of.write((char*) &object, sizeof(T));
of.close();
}
template <class P>
P readBinaryFile(std::string filename)
{
P temp;
std::ifstream ifs(filename, std::ios::in | std::ios::binary);
ifs.read((char*) &temp, sizeof(P));
ifs.close();
return temp;
}
}
#endif
I created a class called GameSettings. The header data is:
#ifndef GAMESETTINGS_H
#define GAMESETTINGS_H
#include <iostream>
#include <string>
#include "SFML\Graphics.hpp"
class GameSettings
{
public:
GameSettings();
GameSettings(std::string playerName, bool sound, int volume, int level);
~GameSettings();
void setPlayerName(std::string playername){ playerName = playername; };
void setSound(bool sound){ this->sound = sound; };
void setVolume(int volume){ this->volume = volume; };
void setLevel(int level){ this->level = level; };
const std::string getPlayerName() { return playerName; }
const bool getSound() { return sound; }
const int getVolume() { return volume; }
const int getLevel() { return level; }
private:
std::string playerName;
bool sound;
int volume;
int level;
};
#endif
With the cpp-data:
#include "GameSettings.h"
GameSettings::GameSettings(std::string playerName, bool sound, int volume, int level)
{
this->playerName = playerName;
this->sound = sound;
this->volume = volume;
this->level = level;
}
GameSettings::GameSettings():
playerName(""),
sound(true),
volume(0),
level(0)
{
}
GameSettings::~GameSettings()
{
}
When I start the main-function:
#include <iostream>
#include "GameSettings.h"
#include "Tools.h"
int main()
{
GameSettings* gs = new GameSettings("Andrew", true, 100, 3);
Tools::writeBinaryFile<GameSettings>("gamesettings.bin", *gs);
gs->setPlayerName("TEST");
*gs = Tools::readBinaryFile<GameSettings>("gamesettings.bin");
std::cout << gs->getPlayerName();
std::getchar();
return 0;
}
an error occurs:
Unhandled exception at 0x5a1cad54 (msvcp100d.dll) in Mohrhuhn.exe: 0xC0000005: Access violation writing location 0xfeeefeee.
Can somebody help me?
Sincerly, Andrew
Upvotes: 3
Views: 888
Reputation: 11962
The template you implement to serialize the object will not work because casting the std::string
to char*
and saving sizeof(std::string)
will not save the content of the string.
Check the saved file, but I guess you need to implement properly serialization and deserialization.
Upvotes: 3
Reputation: 43662
First of all writing down binary files by just dumping them from memory is a bad idea since you might incur in lots of additional problems (e.g. shallow copies, polimorphism, etc..)
return temp;
You are returning a temporary object that is being destroyed after the function exits.
Change your code into
gs = Tools::readBinaryFile<GameSettings>("gamesettings.bin");
...
template <class P>
P* readBinaryFile(std::string filename)
{
P* temp = new P();
std::ifstream ifs(filename, std::ios::in | std::ios::binary);
ifs.read((char*) temp, sizeof(P));
ifs.close();
return temp;
}
and everything will work out properly (psst. remember to free the memory!)
Upvotes: 2
Reputation: 817
I think the root of the trouble is
*gs = Tools::readBinaryFile<GameSettings>("gamesettings.bin");
You read raw bytes to a variable that contains std::string. It may ruin char pointer inside it. So, any call to playerName should fail or result in UB.
Only POD types can be read/write this way. A bit more I found on another web-page: http://www.cplusplus.com/forum/general/39764/
Upvotes: 4