将 wostringstream 转换为 wchar_t* 乱码值

Posted

技术标签:

【中文标题】将 wostringstream 转换为 wchar_t* 乱码值【英文标题】:Converting wostringstream to wchar_t* Garbles Values 【发布时间】:2014-12-31 00:38:37 【问题描述】:

我正在尝试生成一个字符串并将其分配给wchar_t*,但是当我去分配它时,似乎有些东西会混淆字符串。这是一个简化的重现:

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"

当我一次完成所有转换时(如 A),foo 指向的结果值是一堆0xFEEE 字符。但是,如果我一步一步地做(如在 B 中),字符串最终会很好。最奇怪的是,如果赋值后,我评估woss.str()foo 指向的数据突然变为有效(如在C中)。 p>

这让我认为,链式赋值以某种方式返回了一个指向字符最终将去哪里的指针,但它以某种方式跳过了str() 的实际评估,因此实际上并没有填充那里的值。只有当我调用str()(在指针赋值之前或之后)时,数据才会出现在正确的位置。问题是,我不知道什么会导致这种行为......

如果它是相关的,这一切都在辅助线程上运行,但我不认为这很重要,因为我只处理局部变量。想法?

【问题讨论】:

只有一个字。阅读utf8everywhere.org @PavelRadzivilovsky 实际上,这段代码正在填充 Win32 LPCTSRT 结构成员,因此很遗憾必须使用宽字符。不过,好文章。 【参考方案1】:

wostringstream::str() 方法返回一个std::wstring按值。您没有将其分配给任何东西,因此它的生命周期是暂时的,并在表达式完成时结束。您正在调用 std::wstring::c_str() 来保存指向临时数据的指针,然后临时数据被破坏,留下一个杂散的指针,从而在您的后续代码中导致 undefined behavior

不保存std::wstring 的数据指针,而是保存实际的std::wstring 对象,并仅在实际需要时检索其数据指针。

【讨论】:

所以简而言之,B 是正确使用的模式。我过去一直使用链式方法,但我猜那只是在函数调用参数的上下文中,所以指针在调用返回之前是有效的。

以上是关于将 wostringstream 转换为 wchar_t* 乱码值的主要内容,如果未能解决你的问题,请参考以下文章

visual c++ 2013 内存泄漏 wostringstream、imbue 和语言环境方面

wchar_t 和编码

在 C# 中将 FILE_NAME_INFORMATION 转换为字符串

将字符串数组作为缓冲区传递给 C++ 到 C#

比较 2 个 wchar_t 数组

PSTRLPSTR等宏原型