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()
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.
Related
I've searched endlessly on SE for a logical explanation for why this is happening. It is probably something very simple that I've overlooked, however I cannot spot it and would really appreciate some assistance with this.
Last week I implemented a class to read the output of a system call from a .ini file and then find and store the required information into custom objects that are then stored in a vector inside a Config class. It is a Singleton config class storing a unique_ptr for each instance of my custom class that is created.
The thing is, when I implemented this last week on my laptop, I had zero issues reading and writing to my member vector and was able to get it working exactly how I needed it. Since pulling to my desktop computer, this vector, and any STL container that I use as a member of my class, throws a segmentation fault when I try to do anything on it, even get it's size.
I've tried to shorten the code below to only include sections that actually use this vector. I have replaced my config with A, and custom class with T, and no matter where I try to use my member container, or any other test STL containers that I add to the class, I get a segfault.
For the record, I am using Qt with C++11.
Update: This example breaks on line 50 of c.cpp when debugging, and anywhere that tries to call the vector.
Debug points to this line in stl_vector.h
// [23.2.4.2] capacity
/** Returns the number of elements in the %vector. */
size_type
size() const _GLIBCXX_NOEXCEPT
/*-> this line */ { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
main.cpp
#include "c.h"
int main(int argc, char *argv[])
{
C *c = C::getInstance();
delete c;
return 0;
}
t.h - Class stores information from file
#include <string>
class T
{
public:
T();
bool Active();
std::string getA();
void setA(std::string);
private:
std::string a;
};
t.cpp
#include "t.h"
T::T()
{
}
bool T::Active()
{
if(a == "")
{
return false;
}
return true;
}
std::string T::getA()
{
return this->a;
}
void T::setA(std::string newa)
{
this->a = newa;
}
c.h - Class stores T objects and parses file for information
#include "t.h"
#include <QDebug>
#include <vector>
#include <algorithm>
#include <iostream>
#include <memory>
#include <sstream>
#include <fstream>
class C
{
public:
static C* getInstance();
private:
C();
static C* instance;
static bool init;
std::vector<std::unique_ptr<T>> t_list;
void readLines(const std::string&);
};
c.cpp
#include "c.h"
bool C::init = false;
C* C::instance = nullptr;
C::C()
{
system("echo this is a test command > a.ini");
instance->readLines("a.ini");
}
C* C::getInstance()
{
if(!init)
{
instance = new C;
init = true;
}
return instance;
}
void C::readLines(const std::string &path)
{
T* new_t;
std::ifstream file(path.c_str());
if(!file.is_open())
{
qDebug() << "Unable to open " << path.c_str();
}
std::ofstream o("test.txt");
std::string line;
while(std::getline(file, line))
{
// Split string before searching
std::stringstream ss(line);
std::string seg;
std::vector<std::string> split;
std::string left, right;
// Search patterns
size_t find_a = line.find("a");
size_t del = line.find(':');
if(find_a != std::string::npos)
{
o << "test_Size: " << t_list.size() << std::endl;
if(new_t->Active())
{
T* temp = new_t;
std::unique_ptr<T> move_t(temp);
t_list.push_back(std::move(move_t));
}
o << "test: " << t_list.size() << std::endl;
std::string n;
// Check if previous ahas any null elements
// Split string to find a
n = line.substr(line.find("a "));
n = n.substr(n.find(" ", +2));
new_t->setA(n);
}
else
{
continue;
}
}
// Add last a
T* t = new_t;
std::unique_ptr<T> move_t(t);
//t_list.push_back(std::move(move_t));
o << "a: " << t_list.back().get()->getA() << std::endl;
o << t_list.size() << std::endl;
o.close();
file.close();
}
UPDATE after code change:
I see two things now: One is that new_t in C::readlines is never initialized, so this could break when new_t->Active() is called a bit later in the function. However, I believe that the main problem you're running into is in C::C(), where it says
instance->readLines("a.ini");
At this point in the execution, C::instance is not yet initialized -- you're only just constructing the object that would later be assigned to it. Because of this, this in the readlines call is invalid, and any attempt to access object members will cause UB. This latter problem can be fixed by just calling
readLines("a.ini");
in which case the currently constructed object (that will later be instance) is used for this. I have no idea what you want to happen for the first, though, so all I can say is: If you want to have a vector<unique_ptr<T>>, you will have to create objects of type T with either new T() or (arguably preferrably) std::make_unique<T>() and put them in there.
I'll also say that this is a rather ugly way to implement a singleton in C++. I mean, singletons are never really pretty, but if you're going to do it in C++, the usual way is something like the accepted answer of C++ Singleton design pattern .
Old answer:
The problem (if it is the only one, which I cannot verify because you didn't provide an MCVE) is in the lines
T move_t = new_T;
std::unique_ptr<Adapter> ptr_t(&move_t); // <-- particularly this one
m_ts.push_back(std::move(ptr_t));
You're passing a pointer to a local object into a std::unique_ptr, but the whole purpose of std::unique_ptr is to handle objects allocated with new to avoid memory leaks. Not only will the pointer you pass into it be invalid once the scope surrounding this declaration is left, even if that weren't the case the unique_ptr would attempt to delete an object that's not on the heap at the end of its lifecycle. Both problems cause undefined behavior.
To me, it looks as though you really want to use a std::vector<T> instead of std::vector<std::unique_ptr<T>>, but that's a design issue you'll have to answer yourself.
Answering my own question here. I am trying to call a member variable from within the constructor of the object that holds it, so the vector I am trying to access is not yet instantiated and doesn't exist in memory. That is what causes the Segmentation fault to occur, I am trying to access memory that is not allocated yet, hence any call acting on any member of my C class was causing this issue.
I fixed this problem by adding a public function to the class that then calls the private readLines() function. I call that public function from the object that will take ownership of it, and since this occurs after it has been instantiated, the memory is accessible and the problem disappears.
Based on the idea of this entry Is it a good idea to return “ const char * ” from a function?
I thought to extend this with another question I have.
Consider the following code:
#include <string>
#include <cstdio>
const char * GetSomeString()
{
std::string somestlstring;
somestlstring = "Hello World!";
return somestlstring.c_str();
}
int main()
{
const char * tmp = GetSomeString();
printf("%s\n", tmp);
return 0;
}
If I build it with
g++ source.cpp -o executable
and execute that, I get strange symbols displayed. This is because somestlstring is destroyed through the callstack and the pointer you keep after returning became invalid.
My question is: how should I design a method or function that does not have such behaviour without actually declaring additional global variables or potential member functions?
You should drop the whole C mindset and start writing C++:
#include <string>
#include <iostream>
std::string GetSomeString()
{
std::string somestlstring;
somestlstring = "Hello World!";
return somestlstring;
}
int main()
{
std::string tmp = GetSomeString();
std::cout << tmp << std::endl;
return 0;
}
One obvious solution is to make the return type std::string.
how should I design a method or function that does not have such beahviour without actually declaring additional global variables or potential member functions?
Not at all. If you return a const char *, your function is kind of telling the caller "here you have a C string to use, but it stays mine" *), and this implies the caller doesn't have to bother releasing the resources, for example. So you can do this from an instance method (returning a pointer to a field) or you can have a function return a pointer to some static buffer (global variable).
If you want to return a dynamically allocated C string from a function, you must return char * instead and the caller has to free() it when done using it.
That all said, in C++ this doesn't make much sense, except when somehow interfacing with C code. If you want to write C++ code, go with nvoigt's answer.
*) this is thinking in terms of ownership, which is very helpful dealing with manually managed resources. The owner of something is responsible for appropriate cleanup. You can only return a const raw pointer if you don't transfer ownership of the object to the caller.
You are currently referencing the memory of a local std::string object which is destroyed when the object goes out of scope (when returning from the function)
if you really want to return a const char *:
you have to make your std::string static (but only 1 value is shared by your application)
or you have to duplicate the string memory (but you need to free it or you get memory leaks, like happened a lot with the old str() method of the old strstream object, which was later converted to std::string)
But as others said, better stick to C++ std::string (or const reference) as a return value and take c_str() of that returned string when needed for C-style interfaces.
std::string tmp = GetSomeString();
FILE *f = fopen(tmp.c_str(),"r");
The local string variable in the GetSomeString() function will get out of scope after you returned from the funtion. You will be printing random stuff that is in the memory position where the string was before. Try this:
#include <string>
#include <cstdio>
void GetSomeString(std::string& str)
{
str = "Hello World!";
}
int main()
{
std::string str;
GetSomeString(str);
std::cout << str << std::endl;
return 0;
}
I am toying around with streams for a bit and can't get my head around the following.
Here we have a basic ostream ptr that is set to different output streams, whether it is cout, cerr or a file.
// ostream ptr
std::ostream* outstream;
// set output ostream
void setOutput(std::ostream & os)
{
outstream = &os;
}
// write message to ostream
void writeData(const std::string & msg)
{
*outstream << msg << '\n';
}
int main (int argc, char * const argv[])
{
// init to std out
setOutput(std::cout);
writeData("message to cout");
setOutput(std::cerr);
writeData("message to cerr");
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
//fileout.close();
setOutput(std::cout);
writeData("message2 to cout");
return 0;
}
The above works perfectly and shows the strength of the c++ iostream implementation. Perfect.
However, since the setOutput is set by reference the referenced object has to stay in scope. This is where the issue emerges. I want to figure out a way to default the output to std::cout if the ofstream or any other ostream is invalidated. That is, referenced object is or went out of scope.
For example:
// write message to ostream
void writeData(const std::string & msg)
{
if (/*stream or memory is invalid*/)
setOutput(std::cout);
*outstream << msg << '\n';
}
// local fileout goes out of scope
void foo()
{
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
}
int main (int argc, char * const argv[])
{
setOutput(std::cout);
writeData("message to cout");
foo();
/* problem the local fileout is no longer referenced by the ostream ptr*/
/* the following should be redirected to std::cout cuz of default*/
writeData("message2 to cout");
return 0;
}
The above is fine until the foo() returns to the main function. There it goes horrible wrong because the locally defined ofstream is not reachable anymore.
Obviously this is not advisable and the user should realise this. However I want to wrap all this in a logging class and thus keep the state of the object valid even thought this misuse might happen. It will cause an invalidate access violation which can be hard to find.
Concrete question. Is there any way to figure out whether an ostream ptr or any ptr for that matter is still referencing a valid object or memory location?
ps: I could use heap memory and do something with smart pointers but frankly I'd want to keep it like this if possible
Concrete question. Is there any way to figure out whether an ostream ptr or any ptr for that matter is still referencing a valid object or memory location?
No. There is no way to figure that out with raw pointers. Not in standard c++ at least.
You will need to guarantee that the pointed object stays alive as long as it's pointed to.
A common pattern that is used to provide that guarantee is RAII, as detailed in other answers. Another approach to guaranteeing validity of of a pointer is to use a smart pointer instead of a raw one. However, those are not compatible with automatic variables.
It would be OK to keep pointing to dead objects as long as you could guarantee that the pointer is not dereferenced. Which is often difficult to guarantee, because, as already stated, there is no way to test whether the pointed object exists.
This sounds like a great use case for RAII.
Write a class that takes a filename and a std::ostream** as parameters to its constructor. In the constructor of the said class, construct the ofstream (as a member), and set the pointer to the ofstream. In the destructor, revert to stdout.
Then, replace the first two lines of the following function with a declaration of the new class.
void foo()
{
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
}
You should use RAII to force the stream to be set correctly and then set back to std::cout if the object is destroyed.
class OutputStream
{
protected:
static std::ostream*& internalGlobalStateOfOutputStream()
{
static std::ostream* out = &std::cout;
return out;
}
public:
static std::ostream& getOutputStream()
{
return *internalGlobalStateOfOutputStream();
}
};
template<typename T>
class OutputStreamOwner: public OutputStream
{
T ownedStream;
public:
OutputStreamOwner(T&& obj)
: ownedStream(std::move(obj))
{
internalGlobalStateOfOutputStream() = &ownedStream;
}
template<typename... Args>
OutputStreamOwner(Args... args)
: ownedStream(args...)
{
internalGlobalStateOfOutputStream() = &ownedStream;
}
~OutputStreamOwner()
{
internalGlobalStateOfOutputStream() = & std::cout;
}
// Delete copy
OutputStreamOwner(OutputStreamOwner const&) = delete;
OutputStreamOwner& operator(OutputStreamOwner const&) = delete;
};
The usage is:
void foo()
{
OutputStreamOwner<std::ofstream> output("test.txt", std::ofstream::out | std::ofstream::app);
writeData("message to file");
}
A possible approach is to create a RAII class that wraps the stream before passing it into setOutput. This class should be designed to work like shared_ptr such that it maintains a shared ref count. writeData then checks to see if it has the only remaining reference and if so then destroys the ostream and defaults to cout.
You could avoid these complications altogether with a function that takes the stream as input.
void writeData(std::ostream& os, const std::string & msg)
{
os << msg << '\n';
}
You can further refine it by returning the stream, to allow one to chain calls to it:
std::ostream& os writeLine(std::ostream& os, const std::string & msg)
{
os << msg << '\n';
return os;
}
// declare stream
stream << writeLine(stream, "Foo") << writeLine(stream, "Bar");
In fact this function is nicer and easier to maintain, as you don't have to remember which stream is set at any given time. For large programs, this is an important quality.
Concrete question. Is there any way to figure out whether an ostream
ptr or any ptr for that matter is still referencing a valid object or
memory location?
ps: I could use heap memory and do something with smart pointers but
frankly I'd want to keep it like this if possible
No, there is no standard way to test if a raw pointer or reference is still referring to a valid object.
RAII is the standard C++ solution to this type of problem so you should be looking at smart pointers, in my opinion. I am not aware of any library provided smart pointer that would solve this particular problem but an RAII solution based on shared ownership seems the best solution here.
What did I do wrong here?
call
printf(filename(exename));
my function should return filename
const char* filename(const string& str)
{
const char* path;
size_t found;
found=str.find_last_of("/\\");
path = (str.substr(found+1)).c_str();
cout << str.substr(found+1); // ------------> is name ok
printf("\n\n");
printf(path); // ------------> is name not ok random numbers
printf("\n\n");
return path; // ------------> is not ok random numbers
}
str.substr(found+1) returns a temporary std::string.
You call c_str() method on that temporary std::string, and assign the returned pointer to path.
When the temporary is destroyed (at the ;), your path is pointing to garbage.
Make yourself a favor and use C++ (not C mixed with C++), using robust string classes like std::string to store strings (instead of raw potentially-dangling char* pointers):
std::string FileName(const std::string& str)
{
size_t found = str.find_last_of("/\\");
std::string path = str.substr(found+1); // check that is OK
return path;
}
Note also that your use of path variable name is confusing, since the function seems to return the file name (not the path).
A simpler rewrite (without the path variable):
std::string ExtractFileName(const std::string& fullPath)
{
const size_t lastSlashIndex = fullPath.find_last_of("/\\");
return fullPath.substr(lastSlashIndex + 1);
}
printf("Filename = %s\n", ExtractFileName("c:\\some\\dir\\hello.exe").c_str());
...or just use cout (which plays well with std::string and doesn't require c_str() method call to get a raw C string pointer like in C printf() function):
std::cout << ExtractFileName("c:\\some\\dir\\hello.exe");
You are returning a pointer to memory that is held by a temporary (str.substr(found+1)).c_str(). When the temporary goes out of scope, the memory could be overwritten at any time.
str.substr(found+1) is an expression that returns a string. This object is a temporary value which will go away at the end of the execution of the expression that contains it. With .c_str(), you are getting a pointer to memory controlled by this object. After the object's lifetime, this pointer is no longer valid.
Try declaring path as a string, and having your function return a string instead of a pointer.
In general, you should avoid working with raw char * when you are also working with the std::string class. That means you should also avoid using printf; use the std::iostream classes instead.
So I've this issue I can't get fixed :-(
In my .h I've this:
protected:
char* _textPath_1;
FileReader* _reader_3;
in .cpp I've:
_reader_3 = new FileReader();
_textPath_1 = "foo";
_reader_3->openFile(_textPath_1);
And FileReader has this:
private:
char* fileName;
public:
signed int openFile(char* name);
but If I write this (just to test):
signed int FileReader::openFile(char* name) {
std::cout << name << std::endl;
fileName = name;
stream.open(fileName, std::ios::in);
if (!stream.is_open()) {
FileReader::printErrorOpeningFile(fileName);
stream.close();
return -1;
}
return 0;
}
fileName is a char * and I need that it gets the same value (foo) of name. I get an error, and I'm not even able to print name, it just print a blank line.. why?
EDIT: it's not working even using strcpy.. Actually inside the function I can't print the value of name, it's like it has been "deininitialized"
You need to allocate space for your text string _textPath_1.
Try this instead.
char myTextString[] = "foo";
_textPath_1 = myTextString;
This creates a local character array (a character string), which is initialized to "foo\0". It then copies that character string's address to your char pointer _textPath_1. As a LOCAL storage, it will only be valid in the local code block and will not be usable once your code has dropped out of its scope. If you need that string past the local code block, you will need to allocate it from heap memory (using new for instance) and remember to deallocate it after you are done with it.
You cannot use strcpy with your unallocated pointer because strcpy expects the destination char* to be pointing at a character array acting as your destination string buffer. As you haven't allocated any char space at all, it cannot copy "foo" into your _textPath_1, and that's why you get a runtime error when you try to strcpy it.
These and other fun with char* is why std::string was invented. No worries about allocating and deallocating space, having to use strcpy to copy its value, etc etc etc. Consider using std::string _textPath_1 in place of your char* _textPath_1.
You have to allocate _reader_3 before calling the function.
FileReader* _reader_3 = new FileReader;
I assume fileName is your member variable. Accessing pointers without initialization will result in unpredictable results
If you're really defining global variables in your header file:
char* _textPath_1;
FileReader* _reader_3;
Then you shouldn't be doing that. Global variables should be declared in header files, but defined in an implementation file.
This code works fine:
#include <iostream>
#include <fstream>
struct FileReader {
char* fileName;
std::fstream stream;
signed int FileReader::openFile(char* name) {
std::cout << name << std::endl;
fileName = name;
stream.open(fileName, std::ios::in);
if (!stream.is_open()) {
FileReader::printErrorOpeningFile(fileName);
stream.close();
return -1;
}
return 0;
}
void printErrorOpeningFile(char *) {}
};
int main() {
char* _textPath_1;
FileReader* _reader_3;
_reader_3 = new FileReader();
_textPath_1 = "foo";
_reader_3->openFile(_textPath_1);
delete _reader_3;
}