Function works perfectly but changes value after return

Viewed 106

I have a function to concatenate two LPCWSTRs together by converting them to wstrings, adding them, converting it back, and then returning that value (taken from: How to concatenate a LPCWSTR?)

LPCWSTR addLPCWSTRs(LPCWSTR lpcwstr1, LPCWSTR lpcwstr2) {
    //Add the strings together
    std::wstring wstringCombined = std::wstring(lpcwstr1) + std::wstring(lpcwstr2);
    //Convert from wstring back to LPCWSTR
    LPCWSTR lpcwstrCombined = wstringCombined.c_str();
    return lpcwstrCombined;
}

    LPCWSTR BaseURL = L"https://serpapi.com/search.json?tbm=isch?q=";
    LPCWSTR imageQuery = L"baby+animals";

   LPCWSTR URL = addLPCWSTRs(BaseURL, imageQuery);

Before the return statement, the lpcwstrCombined value is correct, when I break before the return statement the debugger shows the value also to be correct.

The correct value should be:

correct value

When I break on the ending curly brace, the value that lpcwstr turns into a bunch of squares before 1-5 random symbols from other languages, and it's always changing.

Examples:

enter image description hereenter image description hereenter image description hereenter image description here

And this is without changing any code, simply resetting the debugger and running again. I have done hours of research on this and so far haven't found anything. A somewhat similar issue with arrays said to use pointers instead of face values but that didn't make a difference. Why does the variable change value outside of the function as soon as it is returned??

Edit: After reading the comments I changed it to:

std::wstring addLPCWSTRs(LPCWSTR lpcwstr1, LPCWSTR lpcwstr2) {
    //Add the strings together
    std::wstring wstringCombined = std::wstring(lpcwstr1) + std::wstring(lpcwstr2);
    //Convert from wstring back to LPCWSTR
    return wstringCombined;
}

LPCWSTR BaseURL = L"https://serpapi.com/search.json?tbm=isch?q=";
LPCWSTR imageQuery = L"baby+animals";
LPCWSTR URL = addLPCWSTRs(BaseURL, imageQuery).c_str();

And the same issue still happens!

1 Answers

The issue is a misunderstanding of the lifetime of your memory. In your first example you have a dangling pointer:

    std::wstring combined = ... 
    // Here you create the string (importantly, its memory)
    
    LPCWSTR lpcwstrCombined = wstringCombined.c_str(); 
    // Make a pointer to the string
    
    return lpcwstrCombined; 
    // return the pointer

 } // end of function the string is destroyed, including it's memory being freed

In your second example you do the same thing, just in a different way:

LPCWSTR URL = addLPCWSTRs(BaseURL, imageQuery).c_str();
              // ^ This is a temporary, at the end of this statement, it will be 
              // destroyed along with its memory.

You need to keep the wstring arround:

std::wstring string_storage = addLPCWSTRs(BaseURL, imageQuery);
LPCWSTR URL = string_storage.c_str();

You can then use the URL for the scope of the string.

That means don't do something like this:

LPCWSTR URL;
{
    std::wstring string_storage = addLPCWSTRs(BaseURL, imageQuery);
    URL = string_storage.c_str();
} // string is destoryed leaving a dangling pointer (just to get you a third 
  // time)
Related