Sure, the fflush is needed. I also used it in my freopen change before calling _setmode. Otherwise remaining part of FILE* buffer is processed by the _O_TEXT together with the new string printed by assert.
If the output is GUI then the narrow assert string is interpreted in ACP because it is printed via MessageBoxA. If the output is stderr then it depends on where the stderr points. If it is file then it is printed as-is with the _O_TEXT conversion. If it is console then the assert string is interpreted according to Output console codepage (retrieved by GetConsoleOutputCP()). IMHO that CRT global locale, CRT thread locale, CRT mbcp, WinAPI ACP, WinAPI OEMCP, WinAPI ThreadLocale CP, WinAPI FileApis CP, WinAPI ConsoleCP, WinAPI ConsoleOutputCP is a mess. Have I forgot some? On Tuesday 23 September 2025 08:15:13 Kirill Makurin wrote: > That actually sounds like a better and simpler approach. > > If you think about, it is possible that assert's expression contains Unicode > characters (I have a few cases like this). I wonder if narrow I/O functions > in old CRTs would just write UTF-8 encoded strings as-is without any special > interpretation of its bytes. Conversion from char to wchar_t would lose them > (in most cases interpret them as single-byte characters for the active > locale, since all 255 bytes represent a valid character). > > I think it would good to add a call to fflush(stderr) before calling _setmode. > ________________________________ > From: Pali Rohár <[email protected]> > Sent: Tuesday, September 23, 2025 5:01 PM > To: Kirill Makurin <[email protected]> > Cc: mingw-w64-public <[email protected]> > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > I have an another idea what could mingw-w64 _assert do. What about just > calling the _setmode(_fileno(stderr), _O_TEXT); and then directly jumps > to CRT's _assert? This can avoid dynamic allocation (required for > converting the ANSI buffer to UNICODE) and also avoid logic which needs > to determinate if the CRT's assert would work with ANSI or not. > > On Monday 08 September 2025 20:48:35 Pali Rohár wrote: > > Feel free to take it. > > > > On Monday 08 September 2025 18:47:04 Kirill Makurin wrote: > > > Tricky but doable. Thanks to Microsoft for complicating things. > > > > > > Would you like me to take care of this, or would you prefer to do it > > > yourself? > > > ________________________________ > > > From: Pali Rohár <[email protected]> > > > Sent: Tuesday, September 9, 2025 3:42 AM > > > To: Kirill Makurin <[email protected]> > > > Cc: mingw-w64-public <[email protected]> > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > > > > > Yes, this is also my observation. > > > > > > For msvcrt40.dll it would be quite tricky as msvcrt40.dll itself does > > > not export _wassert. So it would be needed via GetModuleHandleA to get > > > the msvcrt.dll and call msvcrt's _wassert even for msvcrt40.dll builds. > > > In case msvcrt.dll is not loaded or does not provide _wassert, then > > > calling msvcrt40.dll's _assert should be safe. > > > > > > On Monday 08 September 2025 18:32:19 Kirill Makurin wrote: > > > > I see, so all affected CRTs should also have _wassert. Then it should > > > > to be easy enough to _fix_ _assert. > > > > ________________________________ > > > > From: Pali Rohár <[email protected]> > > > > Sent: Tuesday, September 9, 2025 3:26 AM > > > > To: Kirill Makurin <[email protected]> > > > > Cc: mingw-w64-public <[email protected]> > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > > > > > > > It looks like that those translation modes were introduced in msvcr80 > > > > and are not available in older VC++ versions (like msvcr71, 70, 40, > > > > ...). > > > > They were included into msvcrt.dll system os library in some Windows > > > > version. And because system os msvcrt40.dll just redirects calls to > > > > system os msvcrt.dll, they may be available also in msvcrt40.dll. > > > > > > > > So non-affected should be: crtdll.dll, msvcrt10.dll, msvcrt20.dll, > > > > msvcr40d.dll, msvcrtd.dll, msvcr70.dll, msvcr70d.dll, msvcr71.dll, > > > > msvcr71d.dll. > > > > > > > > Conditionally affected based-on OS are: msvcrt40.dll and msvcrt.dll. > > > > > > > > And all other libs are always affected. > > > > > > > > On Monday 08 September 2025 18:04:55 Kirill Makurin wrote: > > > > > I think this issue will occur in all CRTs which allows to set > > > > > translation mode to any of _O_{W|U8|U16}TEXT. I mentioned that these > > > > > translation modes seem to work starting with msvcrt40.dll, so > > > > > anything other than crtdll.dll, msvcrt10.dll and msvcrt20.dll should > > > > > be affected. > > > > > ________________________________ > > > > > From: Pali Rohár <[email protected]> > > > > > Sent: Tuesday, September 9, 2025 2:59 AM > > > > > To: Kirill Makurin <[email protected]> > > > > > Cc: mingw-w64-public <[email protected]> > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > > > > > > > > > Thanks for info about availability of _wassert. > > > > > > > > > > Do you have exact list of CRT DLL libs which have "broken" _assert in > > > > > this way? I think that it is important to know which CRT DLLs are > > > > > affected as only based on that we can say what is harder or easier to > > > > > implement. > > > > > > > > > > On Monday 08 September 2025 17:54:48 Kirill Makurin wrote: > > > > > > Yes, it possible to change assert's behavior with > > > > > > _set_error_mode[1] functions. > > > > > > > > > > > > Keep in mind that native _wassert is only available starting with > > > > > > msvcr80.dll and in some msvcrt.dll. If we want to do it for all > > > > > > affected CRTs, for CRTs which do not have _wassert, we probably > > > > > > would need to provide our version which mimics CRT behavior and > > > > > > takes _set_error_mode into account. > > > > > > > > > > > > Are you sure it is easier to _fix_ _assert? > > > > > > > > > > > > [1] > > > > > > https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/set-error-mode > > > > > > ________________________________ > > > > > > From: Pali Rohár <[email protected]> > > > > > > Sent: Tuesday, September 9, 2025 2:45 AM > > > > > > To: Kirill Makurin <[email protected]> > > > > > > Cc: mingw-w64-public <[email protected]> > > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and > > > > > > later? > > > > > > > > > > > > assert does not have to print error to console. For GUI > > > > > > applications it > > > > > > prints error via MessageBox. And the default console output can be > > > > > > changed to GUI MessageBox also for console application some CRT call > > > > > > (I do not not right now how is that function called but there is > > > > > > some > > > > > > option). > > > > > > > > > > > > My idea was that _assert replacement would just convert its narrow > > > > > > strings to wide strings and call _wassert function. > > > > > > > > > > > > On Monday 08 September 2025 17:42:10 Kirill Makurin wrote: > > > > > > > I wonder how many people would call _assert function directly, > > > > > > > since it is Microsoft-specific stuff. If such usage is a thing, > > > > > > > it would make sense. > > > > > > > > > > > > > > Maybe we could always map assert to _wassert and provide a > > > > > > > working replacement (for CRTs which do not have it) which prints > > > > > > > message using fwprintf and calls abort()? > > > > > > > ________________________________ > > > > > > > From: Pali Rohár <[email protected]> > > > > > > > Sent: Tuesday, September 9, 2025 2:36 AM > > > > > > > To: Kirill Makurin <[email protected]> > > > > > > > Cc: mingw-w64-public <[email protected]> > > > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and > > > > > > > later? > > > > > > > > > > > > > > Personally I do not like those #ifdes for specific CRT version in > > > > > > > header > > > > > > > files and in past I tried to remove them as many as possible to > > > > > > > make > > > > > > > header files code more cleaner and not dependent on msvcrt vs UCRT > > > > > > > changes. That is why I rather suggested to "fix" the _assert > > > > > > > function, > > > > > > > so also manual call to _assert function would work (which may be > > > > > > > useful > > > > > > > when wrapping assert into custom function and want to propagate > > > > > > > line/file of the caller). > > > > > > > > > > > > > > I do not think that the wchar_t[] vs char[] array size is a > > > > > > > problem. > > > > > > > Assert strings are not such huge. > > > > > > > > > > > > > > On Monday 08 September 2025 17:29:19 Kirill Makurin wrote: > > > > > > > > I did a very quick test and it seems that _O_{U8|U16|W}TEXT > > > > > > > > translation modes are working starting with msvcrt40.dll, so we > > > > > > > > shouldn't bother about this being an issue for msvcrt20.dll and > > > > > > > > older. > > > > > > > > > > > > > > > > assert.h already maps assert to _wassert when _UNICODE or > > > > > > > > UNICODE macros are defined. I think we could just extend this > > > > > > > > condition to include `__MSVCRT_VERSION__ >= 0x0800 || defined > > > > > > > > (_UCRT)`, and if we want to do it for msvcrt.dll, > > > > > > > > `__MSVCRT_VERSION__ == 0x0600`. > > > > > > > > > > > > > > > > The only drawback I see is that stored strings will be wchar[] > > > > > > > > instead of char[], resulting in larger binaries. > > > > > > > > > > > > > > > > ________________________________ > > > > > > > > From: Pali Rohár <[email protected]> > > > > > > > > Sent: Tuesday, September 9, 2025 2:15 AM > > > > > > > > To: Kirill Makurin <[email protected]> > > > > > > > > Cc: mingw-w64-public <[email protected]> > > > > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and > > > > > > > > later? > > > > > > > > > > > > > > > > Now I see that MS documents that _O_U8TEXT does not work > > > > > > > > together with > > > > > > > > printf and hence the assert does not print anything when > > > > > > > > _O_U8TEXT is > > > > > > > > set on stderr. > > > > > > > > > > > > > > > > https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode > > > > > > > > > > > > > > > > Instead of redirecting the assert via #define to _wassert, I > > > > > > > > would > > > > > > > > rather propose to overrride _assert symbol for those affected > > > > > > > > import > > > > > > > > libraries and fix it to work also for _O_U8TEXT. > > > > > > > > > > > > > > > > On Monday 08 September 2025 19:03:09 Pali Rohár wrote: > > > > > > > > > Hello, > > > > > > > > > > > > > > > > > > This is not problem of assert, but rather of the fprintf > > > > > > > > > which assert > > > > > > > > > calls. Same problem can be triggered by using the plain > > > > > > > > > fprintf(stderr,...) > > > > > > > > > instead of assert(0). > > > > > > > > > > > > > > > > > > So I do not think that it makes sense to remap assert as > > > > > > > > > basically all > > > > > > > > > functions which calls fprintf(stderr,...) are affected. > > > > > > > > > > > > > > > > > > Is not it just the _O_U8TEXT which is broken? > > > > > > > > > > > > > > > > > > On Monday 08 September 2025 15:38:09 Kirill Makurin wrote: > > > > > > > > > > Consider the following code: > > > > > > > > > > > > > > > > > > > > ``` > > > > > > > > > > #include <assert.h> > > > > > > > > > > #include <fcntl.h> > > > > > > > > > > #include <io.h> > > > > > > > > > > #include <stdio.h> > > > > > > > > > > > > > > > > > > > > int main (void) { > > > > > > > > > > _setmode (_fileno (stderr), _O_U8TEXT); > > > > > > > > > > assert (0); > > > > > > > > > > return 0; > > > > > > > > > > } > > > > > > > > > > ``` > > > > > > > > > > > > > > > > > > > > When compiled with MSVC, it properly prints message about > > > > > > > > > > failed assertion. When it is compiled with mingw-w64's > > > > > > > > > > headers (Msys2/UCRT64) it produces no output. > > > > > > > > > > > > > > > > > > > > mingw-w64's assert.h maps assert() macro to _wassert only > > > > > > > > > > when _UNICODE or UNICODE is defined. MSVC's assert.h always > > > > > > > > > > maps assert() macro to _wassert and even no longer exposes > > > > > > > > > > _assert function. > > > > > > > > > > > > > > > > > > > > How about we always map assert() macro to _wassert for > > > > > > > > > > msvcr80.dll and later? Since we also emulate _wassert for > > > > > > > > > > msvcrt.dll, it should be OK to map it to _wassert for > > > > > > > > > > msvcrt.dll as well. > > > > > > > > > > > > > > > > > > > > - Kirill Makurin _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
