1

我已经尝试解决这个问题好几天了,但无法让它工作。我在从编译器生成的 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();
}
4

2 回答 2

2

似乎这_ITERATOR_DEBUG_LEVEL应该归咎于调试模式只会崩溃。

我不反对你的解决方案。相反,这是最好的做法。但是,以下是 GoodToKnow:

或者 #define _ITERATOR_DEBUG_LEVEL 0 (甚至更好)在项目中定义的预编译器中设置它。

这将停止 STL 触发异常...参考:https ://msdn.microsoft.com/en-us/library/hh697468.aspx

确保所有嵌套/依赖项目都使用相同的选项编译,或者:_iterator_debug_level 值 '0' 与值 '2' 不匹配

此定义的默认值为 2。

PS 看起来 MS 仍在编译他们内部开发的 STL,即使在工具集 v120 中也是如此

于 2015-06-05T14:34:56.800 回答
0

It was what IInspectable said, but I can't mark it as an answer because it was a comment. My write and my read function now look like this:

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.PlayerLife = Data.PlayerLife;
    fdata.PlayerSuitEnergy = Data.PlayerSuitEnergy;
    fdata.CurrentPower = Data.CurrentPower;
    fdata.PlayerPos = Data.PlayerPos;

    fdata.CurrentGun = Data.CurrentGun;
    fdata.CurrentBulletMod = Data.CurrentBulletMod;

    fdata.ElectricModMult = Data.ElectricModMult;
    fdata.ExplosiveModMult = Data.ExplosiveModMult;
    fdata.CorrosiveModMult = Data.CorrosiveModMult;

    fdata.Guns = Data.Guns;
    fdata.ModsL1 = Data.ModsL1;
    fdata.ModsL2 = Data.ModsL2;
    fdata.ModsL3 = Data.ModsL3;
    fdata.ModsL4 = Data.ModsL4;

    file.write((char*)&fdata,sizeof(FileData));

    int size = Data.MusicStage.length();
    file.write((char*)&size,sizeof(int));
    file.write(Data.MusicStage.c_str(),Data.MusicStage.length()+1);

    size = Data.MusicSubStage.length();
    file.write((char*)&size,sizeof(int));
    file.write(Data.MusicSubStage.c_str(),Data.MusicSubStage.length()+1);

    size = Data.PlotStage.length();
    file.write((char*)&size,sizeof(int));
    file.write(Data.PlotStage.c_str(),Data.PlotStage.length()+1);

    size = Data.PlotSubStage.length();
    file.write((char*)&size,sizeof(int));
    file.write(Data.PlotSubStage.c_str(),Data.PlotSubStage.length()+1);

    size = Data.GameStage.length();
    file.write((char*)&size,sizeof(int));
    file.write(Data.GameStage.c_str(),Data.GameStage.length()+1);

    size = Data.GameSubStage.length();
    file.write((char*)&size,sizeof(int));
    file.write(Data.GameSubStage.c_str(),Data.GameSubStage.length()+1);

    file.close();
}

and my read:

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.PlayerLife = fdata.PlayerLife;
        Data.PlayerSuitEnergy = fdata.PlayerSuitEnergy;
        Data.CurrentPower = fdata.CurrentPower;
        Data.PlayerPos = fdata.PlayerPos;

        Data.CurrentGun = fdata.CurrentGun;
        Data.CurrentBulletMod = fdata.CurrentBulletMod;

        Data.ElectricModMult = fdata.ElectricModMult;
        Data.ExplosiveModMult = fdata.ExplosiveModMult;
        Data.CorrosiveModMult = fdata.CorrosiveModMult;

        Data.Guns = fdata.Guns;
        Data.ModsL1 = fdata.ModsL1;
        Data.ModsL2 = fdata.ModsL2;
        Data.ModsL3 = fdata.ModsL3;
        Data.ModsL4 = fdata.ModsL4;

        int size = 0;
        file.read((char*)&size,sizeof(int));
        char* tmp = new char[size+1];
        file.read(tmp,size+1);
        Data.MusicStage = tmp;
        delete tmp;

        size = 0;
        file.read((char*)&size,sizeof(int));
        tmp = new char[size+1];
        file.read(tmp,size+1);
        Data.MusicSubStage = tmp;
        delete tmp;

        size = 0;
        file.read((char*)&size,sizeof(int));
        tmp = new char[size+1];
        file.read(tmp,size+1);
        Data.PlotStage = tmp;
        delete tmp;

        size = 0;
        file.read((char*)&size,sizeof(int));
        tmp = new char[size+1];
        file.read(tmp,size+1);
        Data.PlotSubStage = tmp;
        delete tmp;
        return HR_Correct;

        size = 0;
        file.read((char*)&size,sizeof(int));
        tmp = new char[size+1];
        file.read(tmp,size+1);
        Data.GameStage = tmp;
        delete tmp;
        return HR_Correct;


        size = 0;
        file.read((char*)&size,sizeof(int));
        tmp = new char[size+1];
        file.read(tmp,size+1);
        Data.PlotSubStage = tmp;
        delete tmp;
        return HR_Correct;

        size = 0;
        file.read((char*)&size,sizeof(int));
        tmp = new char[size+1];
        file.read(tmp,size+1);
        Data.GameSubStage = tmp;
        delete tmp;
        return HR_Correct;
    }

    cout << "Savegame : " << FileName << "not found" << endl;
    return CheckHR(HR_Invalid_Arg);
}

I have one last question though. What problems can I have if an user tries to transfer his saves from one 32 bit computer to a 64 bits one? Endianess is probably not an issue, as the game is windows-only. Thanks anyway, you saved me a LOT of time.

于 2013-09-01T19:35:57.807 回答