【发布时间】:2013-09-01 17:44:16
【问题描述】:
我这几天一直在尝试解决这个问题,但无法让它发挥作用。我在从编译器生成的 POD 结构调用的 std::string 析构函数中的方法“orphan_all”中遇到访问冲突,该结构包含一些 std::string。
struct SaveData
{
SaveData()
{
MusicStage = GameState::MusicStage;
MusicSubStage= GameState::MusicSubStage;
PlotStage = GameState::PlotStage;
PlotSubStage = GameState::PlotSubStage;
GameStage = GameState::GameStage;
GameSubStage = GameState::GameSubStage;
PlayerLife = 100.0f;
PlayerSuitEnergy = 100.0f;
CurrentPower = 0;
PlayerPos = XMFLOAT3(0,0,0);
CurrentGun = 0;
Guns = 0;
ModsL1 = 0;
ModsL2 = 0;
ModsL3 = 0;
ModsL4 = 0;
CurrentBulletMod = (uint)BulletMod::NoMod;
ElectricModMult = 1.0;
ExplosiveModMult = 1.0;
CorrosiveModMult = 1.0;
}
string MusicStage;
string MusicSubStage;
string PlotStage;
string PlotSubStage;
string GameStage;
string GameSubStage;
float PlayerLife;
float PlayerSuitEnergy;
uint CurrentPower;
XMFLOAT3 PlayerPos;
uint CurrentGun;
uint CurrentBulletMod;
float ElectricModMult;
float ExplosiveModMult;
float CorrosiveModMult;
uint Guns;
uint ModsL1;
uint ModsL2;
uint ModsL3;
uint ModsL4;
};
struct FileData
{
uint64 Hash;
uint Version;
SaveData Data;
};
这就是结构。当调用该对象的析构函数时,这里:
HRESULT SavesIO::LoadGameFile(const std::string& FileName,SaveData& Data)
{
ifstream file;
file.open(FileName,ios::binary);
if(file.is_open())
{
FileData fdata;
file.read((char*)&fdata,sizeof(FileData));
if(fdata.Hash != GameHash)
{
cout << "Corrupt Savegame : " << FileName << endl;
return CheckHR(HR_Fail);
}
if(fdata.Version > CurrentVersion)
{
cout << "Savegame version is greater than game version : " << FileName << endl;
return CheckHR(HR_Fail);
}
Data = fdata.Data;
return HR_Correct;
}
cout << "Savegame : " << FileName << "not found" << endl;
return CheckHR(HR_Invalid_Arg);
}
在“orphan_all”中发生了访问冲突,它是从“fdata”中“Data”中的字符串的析构函数调用的,它表示诸如“0xdddddddd”或“0xFEEEFEEE”之类的位置,因此由于某种原因它似乎调用一些已删除的数据。 我使用 HeapValidate() 和 _CrtCheckMemory() 检查了堆损坏,一切似乎都很好。如果我在发行版中编译,问题就会消失。 有人有什么想法吗? 我的系统是 Windows 8 Pro x64,使用 Visual Studio Express 2012,使用 v110 工具集编译。
编辑:我正在写这样的数据:
void SavesIO::SaveGameFile(SaveData Data,const std::string& FileName)
{
ofstream file;
file.open(FileName,ios::binary);
FileData fdata;
fdata.Hash = GameHash;
fdata.Version = CurrentVersion;
fdata.Data = Data;
file.write((char*)&fdata,sizeof(FileData));
file.close();
}
【问题讨论】:
-
您正在(反)序列化复杂结构,就好像它们是 POD 一样。
file.read((char*)&fdata,...)这条线会给你带来麻烦。您实际上是在回读指针(例如包含在您的std::strings 中),这些指针在您将它们写入文件时恰好是有效的。 -
那么序列化/反序列化该结构的好主意是什么?这可能是后来崩溃的原因吗?
-
它是未定义行为的原因,崩溃是一个显着的可观察结果。以文件格式存储字符串通常归结为写入长度后跟单个字符。写作和阅读都需要代码。使用 C++ 流和
operator>>可能是一个解决方案,但如果您要在不同位(32 和 64)或具有不同字节序(小字节序和大字节序)的机器之间共享安全游戏,这不是您的最佳选择。
标签: c++ windows winapi access-violation