Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Temporary std::strings returning junk

Tags:

c++

I'm still learning c++, so please bear with me. I'm writing a simple wrapper around boost filesystem paths -- I'm having strange issues with returning temporary strings. Here's my simple class (this is not exact, but pretty close):

typedef const char* CString;
typedef std::string String;
typedef boost::filesystem::path Path;

class FileReference {

    public:

        FileReference(const char* path) : mPath(path) {};

        // returns a path
        String  path() const {
            return mPath.string();
        };

        // returns a path a c string
        CString c_str() const {
            return mPath.string().c_str();
        };

    private:

        Path    mPath;

}

With the little test code below:

FileReference file("c:\\test.txt");

OutputDebugString(file.path().c_str()); // returns correctly c:\test.txt
OutputDebugString(file.c_str());        // returns junk (ie îþîþîþîþîþîþîþîþîþîþî.....)

I'm pretty sure this has to deal with temporaries, but I can't figure out why that would be -- shouldn't everything be copying correctly?

like image 688
ansiart Avatar asked Jul 06 '12 19:07

ansiart


2 Answers

CString c_str() const {
        return mPath.string().c_str();
    };

mPath.string() returns a copy of a std::string. That copy is stored in a temporary which will be destroyed at the end of this expression.

.c_str() returns a pointer to memory which will be destroyed when the string is destroyed, i.e. at the end of this expression.

You are returning a pointer to memory which is already destroyed.

like image 178
Robᵩ Avatar answered Oct 13 '22 09:10

Robᵩ


Looks like mPath.string() returns a string by value. That temporary string object is destructed as soon as FileReference::c_str() returns, so its c_str() becomes invalid. With such a model, it's not possible to create a c_str() function without introducing some kind of class- or static-level variable for the string.

Consider the following alternatives:

//Returns a string by value (not a pointer!)
//Don't call it c_str() - that'd be misleading
String str() const
{             
     return mPath.string();
} 

or

void str(String &s) const
{             
     s = mPath.string();
} 
like image 31
Seva Alekseyev Avatar answered Oct 13 '22 11:10

Seva Alekseyev