C ++,访问冲突

时间:2014-01-03 23:57:33

标签: c++

我几周前开始学习C ++,现在我的项目出现了问题。

我想编写模板,允许我将对象保存到二进制数据中,然后再加载它们。这是这些模板的代码:

#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

我创建了一个名为GameSettings的类。标题数据是:

#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

使用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()
{
}

当我启动主函数时:

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

发生错误:

Mohrhuhn.exe中0x5a1cad54(msvcp100d.dll)的未处理异常:0xC0000005:访问冲突写入位置0xfeeefeee。

有人能帮助我吗?

真诚地,安德鲁

3 个答案:

答案 0 :(得分:4)

我认为麻烦的根源是

*gs = Tools::readBinaryFile<GameSettings>("gamesettings.bin");

您将原始字节读取到包含std :: string的变量。它可能会破坏它内部的char指针。因此,对playerName的任何调用都应该失败或导致UB。

这种方式只能读/写POD类型。我在另一个网页上找到了更多:http://www.cplusplus.com/forum/general/39764/

答案 1 :(得分:3)

您为序列化对象而实现的模板将无效,因为将std::string强制转换为char*并保存sizeof(std::string)将无法保存字符串的内容。

检查保存的文件,但我想你需要实现正确的序列化和反序列化。

答案 2 :(得分:2)

首先通过从内存中转储二进制文件来写下二进制文件是个坏主意,因为你可能会遇到很多其他问题(例如浅拷贝,polimorphism等等)。

    return temp;

在函数退出后,您将返回一个正在销毁的临时对象。

将您的代码更改为

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

一切都会正常运作(psst。记得释放记忆!)