Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly the debug assert will do in release build?

Tags:

c++

My application behaves strange in release build when handling Chinese characters(wide). I have below line which throw debug assert during debug mode:

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

(Where str is std::wstring) This line throw the assert when in debug mode. I know this is because isspace cannot handle wide char. Instead of isspace, I have to use iswspace.

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

            if (!str.empty())
            { // add str to GUI }

If I press 'Ignore' in the debug assert, the str is added to the GUI properly. But during release mode, the str is not added to GUI.

But if I use iswspace, the str is added to the GUI properly without making any change to my add to GUI logic.

Whats more strange is that some of the Chinese characters are added properly to the GUI during release mode also. For example, str is added to GUI when it is L"左". But not added to GUI when it is L"右".

Did any one had this issue?

My understanding was in release mode, the debug asserts will not be considered and will work similar to 'Ignore'.

Edit:

I debugged it further(in release). Looks like somehow it is not going inside if(!str.empty()) in the case of L"右". But the visual studio debugger still shows L"右" inside str when it hit the break-point at the if condition.

Edit 2: I added std::locale::global(std::locale("")); above the str.erase line. Now it works exactly same in debug and release case and text is added to the GUI.

Here is an example:

#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;
}

This print only "str1 not empty".

like image 981
Jake Avatar asked Jan 26 '23 03:01

Jake


2 Answers

Macro assert does nothing in release mode and will be ignored.

If NDEBUG is defined as a macro name at the point in the source code where is included, then assert does nothing 1,2.

However, just ignoring the assertion doesn't solve the issue. Make your code work in debug mode.

like image 56
masoud Avatar answered Jan 31 '23 21:01

masoud


My understanding was in release mode, the debug asserts will not be considered and will work similar to 'Ignore'.

Yes, but you're ignoring undefined behaviour, because you're passing out-of-range values to isspace.

Read documentation for the features and functions that you use:

The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF.

Really, you should not be using isspace for this. Use a library that supports whatever encoding you're using (UTF-8? UTF-16?)

like image 30
Lightness Races in Orbit Avatar answered Jan 31 '23 22:01

Lightness Races in Orbit