问题
So here's a fun one...
we have a few C libraries which should be platform independent, even though they were developed on linux, because they only rely on the c standard library as defined in ISO/IEC 9899:1999. When we compiled those libraries with MinGW everything seemed to work fine at first, but today we found out that the snprintf() implementation of msvcrt is braindea... sorry, i meant "incompatible" with the definition in the C99 standard.
I would have expected a warning from MinGW, telling me that -std=c99 actually isn't fully supported. Because otherwise, how am i supposed to know?
Is there any alternative c standard library for windows, and most importantly: can MinGW somehow be told to link against it instead of msvcrt?
If not, we would at the very least need a list or something where we can check for other potential portability problems concerning msvcrt and c99.
PS: I know about Cygwin and MSYS2, but i'd rather have native windows binaries (in part because we also use our libraries in Matlab).
Edit: Sorry, i should have explained more clearly what exactly my problem with msvcrt's snprintf() is. According to the standard, snprintf() is required to output a '\0' as the last character, if the output doesn't fit. However, msvcrt just doesn't do that, so the resulting string is no longer properly terminated. I have no idea why anyone would choose to implement snprintf() that way, because to me just omitting the '\0' doesn't make any sense at all.
We have also tried the suggested __USE_MINGW_ANSI_STDIO, but i guess that just fixes the missing format specifiers? At least it didn't seem to make a difference for our specific problem.
回答1:
The standard enforces snprintf
to behave like this:
Otherwise, output characters beyond the n-1st are discarded rather than being written to the array, and a null character is written at the end of the characters actually written into the array.
snprintf
in msvcrt is indeed not the standard one, but a Microsoft version as explained here:
Is snprintf() ALWAYS null terminating?
The following code gives non-compliant results:
#include <stdio.h>
int main (void)
{
char dst[3];
snprintf(dst, 3, "%c%c%c", 'A', 'B', 'C');
for(size_t i=0; i<3; i++)
{
printf("%.2X ", dst[i]);
}
}
I get output 41 42 43
which is not standard compliant. To get standard C, you have to add this before the stdio.h
include:
#define __USE_MINGW_ANSI_STDIO 1
And now you get 41 42 00
which is compliant.
The root of all these program security problems is Microsoft, who have been using non-compliant C libs in their products for the past 20 years.
回答2:
If you need C99 stdio from MinGW-w64, you can define __USE_MINGW_ANSI_STDIO
so that you bypass the msvcrt implementation. It's best to define this through a compiler argument
-D__USE_MINGW_ANSI_STDIO
Alternatively, you could try to use a MinGW-w64 build that is set up to link with the new ucrt, but I don't know of any pre-existing easy-to-use stable builds that are set up that way.
来源:https://stackoverflow.com/questions/57604482/msvcrt-alternative-for-mingw-e-g-to-get-conforming-snprintf