Reputation: 2713
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()
Upvotes: 0
Views: 632
Reputation: 121961
The contained object of the boost::shared_ptr
must be dynamically allocated,
either explicitly via new
or implicitly via boost::make_shared<>
. From boost::shared_ptr
:
The shared_ptr class template stores a pointer to a dynamically allocated object, typically with a C++ new-expression. The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to it is destroyed or reset.
In this case, the std::string
instance is stack allocated and will
be destructed when Read()
returns:
string content = stream.str();
boost::shared_ptr<string> contentPtr(&content);
This results in the shared_ptr
having a dangling pointer and an attempt
to delete
it when the shared_ptr
goes out of scope, causing the error.
The program already has undefined behaviour as any code that attempts to access
the shared_ptr
after Read()
is dereferencing a dangling pointer.
To correct, dynamically allocate the std::string
:
return boost::make_shared<std::string>(stream.str());
Or, simpler, just return and store a std::string
instance instead:
return stream.str();
as the compiler should be able to use return value optimization.
Note that c++11 introduced smart pointers, std::shared_ptr
among them.
Upvotes: 5