【问题标题】:Boost shared pointer "runtime error" after it gets end of scope在范围结束后提升共享指针“运行时错误”
【发布时间】:2013-05-07 14:26:22
【问题描述】:

我正在练习 boost,现在我正在测试 boost 共享指针。我有一个可以读取文件的 Util 类。读取文件后,我的“读取”方法返回指向文件内容的 boost::shared_ptr。然后我将此共享指针传递给我的 Parser 类,该类逐行解析字符串。解析完成后,在我的 Parser 类构造函数的末尾(在'}')我得到一个“运行时错误”,它指向一个 boost 头文件。更具体地说,checked_delete.hpp 到“删除 x”行:

template<class T> inline void checked_delete(T * x) {
   // intentionally complex - simplification causes regressions
   typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
   (void) sizeof(type_must_be_complete);
   delete x;
}

简化的代码如下所示:

class File {
    string _path;
public:
    File(string path)
    ~File()
    void Open();
    boost::shared_ptr<string> Read();
    void Close();
};

class Parse {
public:
    Parse(string path) {
        File file = File(path);
        file.Open();
        boost::shared_ptr<string> fileContentPtr = file.Read();
        StartParsing(fileContentPtr);
        file.Close();
    }
    ~Parse();
    StartParsing(boost::shared_ptr<string> fileContentPtr);
};

int main() {
string path = "<some path to my file>";
Parse(path);
}

任何人都可以给我一个提示,我做错了什么?提前致谢!

编辑:我的 Read() 函数:

boost::shared_ptr<string> File::Read() {
    if(file.is_open()) {
        ostringstream stream;
        stream << file.rdbuf();
        string content = stream.str();
        boost::shared_ptr<string> contentPtr(&content);
        return contentPtr;
    }
    else {
        throw std::runtime_error("File isn't opened");
    }
}

其中“file”变量是一个在 Open() 中使用的 std::fstream 文件

【问题讨论】:

  • 你能发布Read()函数定义吗?
  • 您的简化代码也有问题吗? File::Read 的实现是什么?我没有看到 Parse 构造函数的实现有直接的问题,所以我的猜测是问题可能与 File::Read 相关。
  • 顺便说一句,我强烈建议通过 const 引用将 'path' 参数传递给 Parse 构造函数,以避免您进行不必要的复制。
  • 是的,我将它添加为 const,只是在我输入时忘记了它。稍后我将添加我的 Read() 函数。

标签: c++ boost shared-ptr


【解决方案1】:

boost::shared_ptr 包含的对象必须是动态分配的, 通过new 显式或通过boost::make_shared&lt;&gt; 隐式传递。来自boost::shared_ptr

shared_ptr 类模板存储一个指向动态分配对象的指针,通常使用 C++ 新表达式。当指向它的最后一个 shared_ptr 被销毁或重置时,指向的对象保证被删除。

在这种情况下,std::string 实例是堆栈分配的,并将 当Read() 返回时被破坏:

string content = stream.str();
boost::shared_ptr<string> contentPtr(&content);

这导致shared_ptr 有一个悬空指针和一个尝试 当shared_ptr 超出范围时,delete 它会导致错误。

该程序已经具有未定义的行为,因为任何尝试访问的代码 shared_ptrRead() 之后的 shared_ptr 正在取消对悬空指针的引用。

要更正,动态分配std::string

return boost::make_shared<std::string>(stream.str());

或者,更简单,只需返回并存储一个 std::string 实例:

return stream.str();

因为编译器应该能够使用return value optimization


注意c++11在其中引入了smart pointersstd::shared_ptr

【讨论】:

  • 感谢您的详细解答。假设我正在处理大型 txt 文件,一直复制该字符串不是浪费吗?这可能是一个愚蠢的问题。 :)
  • @Silex,编译器可能会使用 VRO 优化它(或者在 c++11 中,如果 NVRO 不可用,它可能是 move()d)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 2011-06-10
  • 2018-06-03
  • 2012-10-19
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
相关资源
最近更新 更多