调试断言在发布版本中将做什么?

时间:2019-07-01 08:03:31

标签: c++

在处理汉字(宽)时,我的应用程序在发行版中表现得很奇怪。 我在调试模式下抛出调试断言的行如下:

str.erase(std::remove_if(str.begin(), str.end(), isspace), str.end());

(str是std :: wstring的地方) 在调试模式下,此行引发断言。我知道这是因为 isspace 无法处理宽字符。代替 isspace ,我必须使用 iswspace

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“左” 时,会将str添加到GUI。但当它为 L“右” 时未添加到GUI。

有人遇到过这个问题吗?

我的理解是处于发布模式,因此不会考虑调试断言,并且其工作原理类似于'忽略'。

编辑:

我进一步调试了它(在发行版中)。在 L“右” 的情况下,if(!str.empty())似乎不会进入内部。但是,Visual Studio调试器在if条件下达到断点时,仍在str内部显示L“右”。

编辑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不为空”。

3 个答案:

答案 0 :(得分:5)

assert在发布模式下不执行任何操作,将被忽略。

  

如果在源代码中的点处将NDEBUG定义为宏名    12

但是,仅忽略断言并不能解决问题。使您的代码在调试模式下工作。

答案 1 :(得分:2)

  

我的理解是处于发布模式,因此不会考虑调试断言,并且其工作方式类似于“忽略”。

是的,但是您忽略了未定义的行为,因为您正在将超出范围的值传递给isspace

阅读documentation,了解您使用的功能:

  

如果ch的值不能表示为unsigned char并且不等于EOF,则行为不确定。

真的,您不应为此使用isspace。使用支持您正在使用的任何编码的库(UTF-8?UTF-16?)

答案 2 :(得分:1)

对宽字符串使用iswspace(及其宽字符弟兄):

#include <string>
#include <algorithm>
#include <iostream>

int main(int argc, char* argv[])
{
    std::wstring str1 = L"左";
    std::wstring str2 = L"右";
    str1.erase(std::remove_if(str1.begin(), str1.end(), iswspace), str1.end());
    if (!str1.empty())
    {
        std::wcout << L"str1 not empty\n";
    }
    str2.erase(std::remove_if(str2.begin(), str2.end(), iswspace), str2.end());
    if (!str2.empty())
    {
        std::wcout << L"str2 not empty\n";
    }
    getchar();
    return 0;
}

输出:

str1 not empty
str2 not empty

在发布模式或调试模式下,isspace版本是“有效”还是“无效”都是红色鲱鱼,因为您一直在调用未定义的行为

CppReference.com on isspace,请强调:

  

如果ch的值不能表示为unsigned char并且不等于EOF,则行为未定义