MooseBoys
MooseBoys

Reputation: 6793

Converting wostringstream to wchar_t* Garbles Values

I'm trying to generate a string and assign it to a wchar_t* but something seems to be garbling the string when I go to assign it. Here's a simplified repro:

wostringstream woss;
woss << L"Test String";

// A: this doesn't work:
const wchar_t* foo = woss.str().c_str();
wcout << foo << endl; // "????????????????????????"

// B: this works:
wstring bar = woss.str();
const wchar_t* foo = foo.c_str();
wcout << foo << endl; // "Test String"

// C: this also works!?:
const wchar_t* foo = woss.str().c_str();
wstring bar = woss.str();
wcout << foo << endl; // "Test String"

When I do the conversion all at once (as in A), the resulting values pointed to by foo are a bunch of 0xFEEE characters. If I do it step by step however (as in B), the string ends up fine. The weirdest thing is that if, after the assignment, I evaluate woss.str(), the data pointed to by foo suddenly becomes valid (as in C).

This leads me to think that somehow the chained assignment is returning a pointer to where the characters will eventually go, but it's somehow skipping the actual evaluation of str() and so isn't actually populating the values there. Only once I call str() (either before or after the pointer assingment) does the data end up in the right place. The thing is, I have no idea what would cause this behavior...

In case it's relevant, this is all running on a secondary thread, but I wouldn't expect that to matter since I'm only dealing with local variables. Thoughts?

Upvotes: 0

Views: 883

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409176

The wostringstream::str() method returns a std::wstring by value. You are not assigning that to anything, so its lifetime is temporary and ends when the expression is finished. You are calling std::wstring::c_str() to save a pointer to the temporary's data, then the temporary gets destructed afterwards, leaving you with a stray pointer, thus causing undefined behavior in your subsequent code.

Instead of saving the std::wstring's data pointer, save the actual std::wstring object, and retrieve its data pointer only when actually needed.

Upvotes: 6

Related Questions