【问题标题】:Runtime Error upon returning pointer返回指针时的运行时错误
【发布时间】:2015-03-08 01:14:30
【问题描述】:

这是一个从文件中读取二进制数据然后返回指向对象的指针的方法。

Database* Database::open(const char *path)
{
    ifstream ifs;
    ifs.open(path, ios::in | ios::binary);
    if(!ifs)
    {
        cerr << "Failed to open database." << endl;
        return NULL;
    }
    config_vars cfg;
    ifs.read((char*)&cfg, sizeof(config_vars));
    if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
    {
        cerr << "Failed to read database file." << endl;
        return NULL;
    }
    ifs.close();

    Database *db = new Database();
    db->config = cfg;
    db->db_path = string(path);
    return db;
};

调用栈显示是通过销毁config_vars结构体的字符串成员来表示的,其定义如下:

struct config_vars
{
    string name;
    string author;
    int date;
};

我无法真正理解导致访问冲突的原因。如果重要的话,该方法也是静态的。

调用栈:

msvcp100d.dll!std::_Container_base12::_Orphan_all()  Line 201 + 0x12 bytes  C++
    NoDB.exe!std::_String_val<char,std::allocator<char> >::~_String_val<char,std::allocator<char> >()  Line 478 + 0xb bytes C++
    NoDB.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >()  Line 754 + 0xf bytes C++
    NoDB.exe!config_vars::~config_vars()  + 0x54 bytes  C++
>   NoDB.exe!Database::open(const char * path)  Line 24 + 0x1b bytes    C++

【问题讨论】:

  • 什么访问冲突?你没有在这里显示任何东西。 Database 是什么?错误是什么?你如何运行这段代码?
  • @Mat:这与序列化向量有什么关系?请不要滥用你的欺骗锤。
  • @Selenir:在继续之前请阅读stackoverflow.com/help/mcve
  • @Mat:但这不是完全相同的问题。你不能只是欺骗关闭所有可能有相似答案的东西。

标签: c++ string memory struct destructor


【解决方案1】:

std::string 类只不过是一个带有指针的数据成员。因此,无论您使用ifs.read((char*)&amp;cfg, sizeof(config_vars)); 读入cfg 的内容,都是将指针设置为完全无效的指针。这就是您的访问违规的根源。

您需要做的是单独读取 cfg 的每个成员。根据 cfg 文件的格式,您可能可以执行以下操作:

ifs >> cfg.name;
ifs >> cfg.author;
ifs >> date;

但这可能不会那么容易。

无论如何,这就是您遇到访问冲突的原因。您需要找到不同的方法,但这将是一个不同的问题!祝你好运!

【讨论】:

  • 但问题是它确实从文件中正确读取数据,当方法返回指针并且所有局部变量都被破坏时会发生访问冲突,如调用堆栈中所示。
  • @Selenir - config_vars cfg; 这需要在函数结束时被破坏,而你的“读取”把它搞砸了。这就是简单的解释。
  • 不,读取不正确。您可能不会收到错误代码,但是当您按照自己的方式进行操作时,您会在内存中跺脚。在堆栈清理之前,错误不会出现。字符串析构函数试图删除一个指向完全无效的指针。
  • 好的,我明白了。感谢您的帮助。
【解决方案2】:

C++ 对象不是字符串。它们不仅仅是字节的平面集合。通常,您不能以这种方式对它们进行反序列化。您将需要一个适当的序列化库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    • 2022-11-13
    • 2021-12-22
    • 1970-01-01
    相关资源
    最近更新 更多