0

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?

2
  • just one word. read utf8everywhere.org Commented Jan 1, 2015 at 1:56
  • 1
    @PavelRadzivilovsky In reality this code was populating a Win32 LPCTSRT struct member, so unfortunately must use wide chars. Still, good article. Commented Jan 2, 2015 at 18:12

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

1 Comment

So in a nutshell, B is the correct pattern to use. I've always used the chained method in the past but I guess that was only ever in the context of a function call argument, so the pointer is valid until the call returns.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.