我的应用程序在处理中文字符(宽字符)时,在发布版本中表现奇怪。我有以下代码行,在调试模式下会抛出 debug assert:
如果我在调试断言中按下“忽略”,则 str 会被正确地添加到GUI中。但在发布模式下,str 不会被添加到GUI中。
但是如果我使用 iswspace,str 就会被正确地添加到 GUI 中,而不需要对我的添加到 GUI 逻辑进行任何更改。
更奇怪的是,有些中文字符在发布模式下也能够正确地添加到 GUI 中。例如,当 str 为 L"左" 时,它会被添加到 GUI 中。但当 str 为 L"右" 时就不会添加到 GUI 中了。
有人遇到过这个问题吗?
我理解的是,在发布模式下,调试断言不会被考虑,并且会像 "忽略" 一样工作。
编辑:
我进一步调试了它(在发布模式下)。看起来在L"右" 的情况下它并没有进入 if(!str.empty())。但是Visual Studio调试器在 if 条件处命中断点时仍然显示 L"右" 在 str 中。
编辑 2: 我在 str.erase 行上面添加了
这是一个例子:
str.erase(std::remove_if(str.begin(), str.end(), isspace), str.end());
(其中str为std::wstring)
在调试模式下,此行会抛出断言。我知道这是因为 isspace 无法处理宽字符。所以我必须使用 iswspace 代替 isspace。
str.erase(std::remove_if(str.begin(), str.end(), isspace), str.end());
if (!str.empty())
{ // add str to GUI }
如果我在调试断言中按下“忽略”,则 str 会被正确地添加到GUI中。但在发布模式下,str 不会被添加到GUI中。
但是如果我使用 iswspace,str 就会被正确地添加到 GUI 中,而不需要对我的添加到 GUI 逻辑进行任何更改。
更奇怪的是,有些中文字符在发布模式下也能够正确地添加到 GUI 中。例如,当 str 为 L"左" 时,它会被添加到 GUI 中。但当 str 为 L"右" 时就不会添加到 GUI 中了。
有人遇到过这个问题吗?
我理解的是,在发布模式下,调试断言不会被考虑,并且会像 "忽略" 一样工作。
编辑:
我进一步调试了它(在发布模式下)。看起来在L"右" 的情况下它并没有进入 if(!str.empty())。但是Visual Studio调试器在 if 条件处命中断点时仍然显示 L"右" 在 str 中。
编辑 2: 我在 str.erase 行上面添加了
std::locale::global(std::locale(""));
。
现在它在调试和发布情况下的工作完全相同,文本被添加到 GUI 中。这是一个例子:
#include <string>
#include <iostream>
#include <algorithm>
int main(int argc, char* argv[])
{
std::wstring str1 = L"左";
std::wstring str2 = L"右";
str1.erase(std::remove_if(str1.begin(), str1.end(), isspace), str1.end());
if (!str1.empty())
{
std::wcout << L"str1 not empty\n";
}
str2.erase(std::remove_if(str2.begin(), str2.end(), isspace), str2.end());
if (!str2.empty())
{
std::wcout << L"str2 not empty\n";
}
getchar();
return 0;
}
这将仅打印“str1不为空”。
assert
可能不是唯一的差异;Visual C++ 库往往会在简单的 assert 之外进行更广泛的调试检查。 - MSaltersstr
类型的想法会很好,因为在std::basic_string<char>
上使用iswspace
并不起作用。通常来说,如果你在处理 Unicode,你应该使用 ICU,因为标准库对于 Unicode 的处理能力非常有限,即使是更新版本也仍然存在一些问题。你可以提供一个自包含示例吗? - DevSolarL"..."
是宽字符串字面值。根据(实现定义的)编码方式,这样的字面值中的宽字符可能包含空字节。如果您将其传递给std::basic_string<char>
,那么该空字节可能会被解释为字符串结尾。我认为现在是提供一个[mcve]的时候了,因为现在我们都只是在猜测。 - DevSolar