On Sunday 21 June 2026 07:59:06 Kirill Makurin wrote:
> Pali Rohár <[email protected]> wrote:
> 
> > On Thursday 18 June 2026 12:36:04 Kirill Makurin wrote:
> >> Previous implementaion used `wcstombs` to convert its wide string 
> >> arguments to
> >> narrow strings, which are then passed to `_assert`; function `wcstombs` is
> >> thread-unsafe in its nature and should not be used.
> >
> > It is really truth that wcstombs is thread-unsafe? I had an impression
> > that wcstombs is using its own thread local buffer, and that it is safe
> > to use it (I used it many times in this way). So I would like to know
> > more information.
> 
> I made this assumption because C89 mb* functions (mblen, mbtowc and mbstowcs) 
> are not threads-safe. What's interesting is that their _l versions seem to be 
> thread-safe, at least based on my tests.

Linux manapages specifies that mblen and mbtowc are not thread-safe. But
the mbstowcs and wcstombs are thread safe.


And this can be also simple deduced from C99 (n1256.pdf) from section
"7.20.7 Multibyte/wide character conversion functions" which applies for
"mblen", "mbtowc" and "wctomb":
"Subsequent calls with s as other than a null pointer cause the internal
conversion state of the function to be altered as necessary."

Obviously this is not thread safe. Or rather I have feeling from this
description that the state has to be shared with all threads, which
should allow threads if they are properly synchronized to do subsequent
calls from different threads.


And for "mbstowcs" and "wcstombs" is written:

Section "7.20.8.1 The mbstowcs function":
"Each multibyte character is converted as if by a call to the mbtowc
function, except that the conversion state of the mbtowc function is not
affected."

Section "7.20.8.2 The wcstombs function":
"Each wide character is converted as if by a call to the wctomb
function, except that the conversion state of the wctomb function is not
affected."

Which explicitly forbids usage of that thread-racy state variables.

Note that C89 does not have wchar_t and its functions. It was firstly
added in C95. But I do not know about any publicly available draft of
C95, there is only that paid ISO spec. So for the best wording is to use
public C99 draft.

> I wrote a test program (attached), and it seems like C89 wc* functions 
> (wctomb and wcstombs) are really thread-safe on Windows. Even so, thread-safe 
> code should use `wcrtomb` and `wcsrtombs` instead.

Quite interesting if the wctomb on Windows is really thread safe.

On the other hand, I think that wcstombs should be thread safe on all
implementations. It needs internal state just on the stack as it is not
shared with any other followup wcstombs call. And same for mbstowcs.

I was using wcstombs and mbstowcs in this way in multithread apps lot of
times and I even was not thinking that there could be a problem. So that
is why I'm surprised if there could be any issues.

> I noticed that pre-msvcr80.dll's `w*printf` functions do not handle multibyte 
> narrow strings properly.
> 
> >> Other than thread-safety, `wcstombs` has other issues:
> >>
> >> 1. It uses code page used by active CRT locale; this may be an issue when 
> >> assert
> >>   message is displayed in message box, which assumes string to be encoded 
> >> using
> >>   active ANSI code page.
> >
> > Case 1. for sure when displaying to GUI MessageBoxA() it is needed to
> > use ACP for conversion. But I still think that for fprintf output it
> > should be used the CRT locale, not the ACP.
> 
> Absolutely; this is where we could use `_set_error_mode` to choose proper 
> code page.
> 
> >> 2. In case when entire string cannot be converted to target code page, it 
> >> does
> >>   not allow to convert only part of the string.
> >
> > This is also good point. WinAPI WideCharToMultiByte() can solve it. Or
> > if we want to stick with CRT (which I think that it is a good idea for
> > CRT functions) then loop over wcrtomb() could be used.
> 
> This is not an option when we convert to ACP, so I think using 
> `WideCharToMultiByte` is the simplest solution.
> 
> - Kirill Makurin

Yes, this is what I have already figured out, use just the
WideCharToMultiByte().


_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to