0

I am practicing with boost and now I am testing boost shared pointers. I have a Util class which can read files. After I read the file, my "Read" method gives back a boost::shared_ptr which points to the file content. Then I pass this shared pointer to my Parser class, which parses the string line by line. After the parsing is done, then at the end of my Parser class constructor (at '}') I get a "runtime error" which points to a boost header file. More specifically to checked_delete.hpp to the "delete x" line:

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

A simplifyed code looks something like this:

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

Anybody can give me a hint, what am I doing wrong? Thanks in advance!

EDIT: My Read() function:

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

Where "file" variable is a std::fstream file which is used in Open()

4

1 回答 1

5

包含的对象boost::shared_ptr必须是动态分配的,无论是显式通过new还是隐式通过boost::make_shared<>。来自boost::shared_ptr

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

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

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

这导致有一个悬空指针并在超出范围时shared_ptr尝试使用delete它,从而导致错误。shared_ptr

该程序已经具有未定义的行为,因为任何尝试访问shared_ptrafterRead()的代码都在取消引用一个悬空指针。

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

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

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

return stream.str();

作为编译器应该能够使用返回值优化


请注意,c++11 在其中引入了智能指针std::shared_ptr

于 2013-05-13T14:28:37.567 回答