1

私はこれを何日も解決しようとしてきましたが、うまくいきません。std::string を含む、コンパイラによって生成された POD 構造体から呼び出される std::string デストラクタのメソッド "orphan_all" でアクセス違反が発生します。

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

「fdata」内の「Data」内の文字列のデストラクタから呼び出される「orphan_all」内でアクセス違反が発生し、「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

0

IInspectableが言ったことですが、コメントだったので回答としてマークできません。私の書き込みと読み取り関数は次のようになります。

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

最後に 1 つ質問があります。ユーザーがセーブ データを 32 ビット コンピュータから 64 ビット コンピュータに転送しようとすると、どのような問題が発生する可能性がありますか? ゲームは Windows 専用であるため、エンディアンはおそらく問題になりません。とにかくありがとう、あなたは私に多くの時間を節約しました。

于 2013-09-01T19:35:57.807 に答える