windows 仅在调试时std::string析构函数中出现访问冲突

eoxn13cs  于 2022-12-14  发布在  Windows
关注(0)|答案(3)|浏览(133)

我已经试着解决这个问题好几天了,但是不能让它工作。我在一个std::string析构函数的方法“orphan_all”中得到了一个访问冲突,这个析构函数是从编译器生成的POD结构调用的,它包含一些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”或“0xFEEEEEEE”,因此出于某种原因,它似乎调用了一些已删除的数据。我使用HeapValidate检查了堆损坏()和_Crt检查内存()而且一切似乎都很好。如果我在发行版中编译,问题就会消失。有人知道吗?我的系统是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();
}
khbbv19g

khbbv19g1#

_ITERATOR_DEBUG_LEVEL似乎是导致调试模式崩溃的原因。
我并不反对你的解决方案。相反,这是最好的办法。但是,下面是GoodToKnow:
#define _ITERATOR_DEBUG_LEVEL 0或者(更好的)在项目的预编译器定义中设置它。
这将停止STL以引发异常...参考:https://msdn.microsoft.com/en-us/library/hh697468.aspx
确保所有嵌套/相关项目都是使用相同的选项编译的,或者:_iterator_debug_level value '0' doesn't match value '2'
此定义默认值为2。
PS看起来微软仍然在编译他们内部开发的STL,甚至在工具集v120中

vxqlmq5t

vxqlmq5t2#

这是IInspectable所说的内容,但我不能将其标记为答案,因为它是一个注解。我的write和read函数现在看起来如下:

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();
}

我读者:

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);
}

我还有最后一个问题。如果一个用户试图把他的存档从一台32位的电脑转移到一台64位的电脑上,我会遇到什么问题呢?字节序可能不是问题,因为游戏是windows专用的。无论如何,谢谢你,你节省了我很多时间。

dced5bon

dced5bon3#

我得到了AccessViolationxmemorystd::string析构函数的调用堆栈,因为我将string从用Debug编译的程序集传递到另一个用Release编译的程序集。

相关问题