Search code examples
c++optimizationmemory-managementstackstdstring

std::string::c_str() overwrittes the previous one returned by a function


I could not understand that how can be the pointers same when the text size is equal. It seems like firstStringObj::c_str() overwrittes the previous one's pointer.

#include <iostream>
#include <string>
#include <string>
#include <stdio.h>

std::string getConstCharAndModifyItWithANewString( const char* constchar )
{
    std::string stringAtStack( constchar );
    stringAtStack += "::isModified";
    return stringAtStack;
}

int main()
{
    const char* firstConstCharPointer = getConstCharAndModifyItWithANewString("Hi!").c_str();
    std::string firstStringObj = "Hi+";

    printf(" firstConstCharPointer(%s)(%p)\nfirstStringObj(%s)(%p)\n\n", firstConstCharPointer,firstConstCharPointer, firstStringObj.c_str(),     firstStringObj.c_str()  );
}

OUTPUT: firstConstCharPointer(Hi+)(0x4593eb8) firstStringObj(Hi+)(0x4593eb8)


Solution

  • Your function returns a temporary std::string object. After the firstConstCharPointer variable is assigned and the expression is complete, that temporary object gets destroyed, freeing its allocated memory block and leaving the variable pointing at freed memory. This is known as a dangling pointer.

    firstStringObj then allocates a new memory block, which happens to be reusing the same memory block that the temp std::string had previously allocated and freed. So the dangling pointer happens to now be pointing at valid memory again. That is why your printf() statement is able to display the same memory address and content for both strings.

    But this is undefined behavior. The memory block that gets allocated each time is completely up to the string's Allocator to decide. The second std::string could just as easily have allocated a completely different memory block, and then the code would be more likely to crash, or at least print garbage, when it tries to dereference the dangling pointer that is still pointing at invalid memory.

    In order for your code to work, you need to change firstConstCharPointer to a std::string object so the temp std::string gets copied properly, eg:

    #include <iostream>
    #include <string>
    #include <cstdio>
    
    std::string getConstCharAndModifyItWithANewString( const char* constchar )
    {
        std::string stringAtStack( constchar );
        stringAtStack += "::isModified";
        return stringAtStack;
    }
    
    int main()
    {
        const std::string firstConstStringObj = getConstCharAndModifyItWithANewString("Hi!");
        std::string secondStringObj = "Hi!";
    
        std::printf(" firstConstStringObj(%s)(%p)\nsecondStringObj(%s)(%p)\n\n", firstConstStringObj.c_str(), firstConstStringObj.c_str(), secondStringObj.c_str(), secondStringObj.c_str());
    }