Re: Warning, gcc 10.2.0 incompatible changes!
Posted: Wed Sep 23, 2020 5:24 pm
I tried it. The strings appear fine in the compiled binary, but it crashes anyway. Perhaps the buffer you're writing the string into is too small?
The Place to Start for Operating System Developers
https://f.osdev.org/
Code: Select all
/* We are activating __USE_MINGW_ANSI_STDIO for various define indicators.
* printf ll modifier (unsupported by msvcrt.dll) is required by C99 and C++11 standards. */
#if (defined (_POSIX) || defined (_POSIX_SOURCE) || defined (_POSIX_C_SOURCE) \
|| defined (_ISOC99_SOURCE) \
|| (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && __MSVCRT_VERSION__ < 0xE00) \
|| (defined (__cplusplus) && __cplusplus >= 201103L && __MSVCRT_VERSION__ < 0xE00) \
|| defined (_XOPEN_SOURCE) || defined (_XOPEN_SOURCE_EXTENDED) \
|| defined (_GNU_SOURCE) \
|| defined (_SVID_SOURCE)) \
&& !defined(__USE_MINGW_ANSI_STDIO)
/* Enable __USE_MINGW_ANSI_STDIO if user did _not_ specify it explicitly... */
# define __USE_MINGW_ANSI_STDIO 1
#endif
Code: Select all
/* 7.8.1 Macros for format specifiers
*
* MS runtime does not yet understand C9x standard "ll"
* length specifier. It appears to treat "ll" as "l".
* The non-standard I64 length specifier causes warning in GCC,
* but understood by MS runtime functions.
*/
#if defined(_UCRT) || __USE_MINGW_ANSI_STDIO
#define PRId64 "lld"
#define PRIi64 "lli"
#define PRIo64 "llo"
#define PRIu64 "llu"
#define PRIx64 "llx"
#define PRIX64 "llX"
#else
#define PRId64 "I64d"
#define PRIi64 "I64i"
#define PRIo64 "I64o"
#define PRIu64 "I64u"
#define PRIx64 "I64x"
#define PRIX64 "I64X"
#endif
Code: Select all
#include <stdio.h>
#include <inttypes.h>
#include <windows.h>
int wmain(int argc, wchar_t ** argv, wchar_t **env)
{
unsigned long long a = 1337;
wchar_t str[100];
wsprintfW(str, L"%" PRIu64 "\n", a);
wprintf(str); // Prints lu, not the number
return 0;
}
Code: Select all
wsprintfW(str, L"%llu", a);
Code: Select all
#include <stdio.h>
#undef __USE_MINGW_ANSI_STDIO
#include <inttypes.h>
#include <windows.h>
int wmain(int argc, wchar_t ** argv, wchar_t **env)
{
unsigned long long a = 1337;
wchar_t str[100];
wsprintfW(str, L"%" PRIu64 "\n", a);
wprintf(str); // Prints 1337
return 0;
}
Code: Select all
gcc -Wall -municode a.c
Code: Select all
disks_win.c:33:10: fatal error: ddk/ntdddisk.h: No such file or directory
Code: Select all
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
/* 7.8.1 Macros for format specifiers
*
* MS runtime does not yet understand C9x standard "ll"
* length specifier. It appears to treat "ll" as "l".
* The non-standard I64 length specifier causes warning in GCC,
* but understood by MS runtime functions.
*/
. . .
#define PRIu64 "I64u"
. . .
That is false. PRIu64 is defined as a macro that expands to that printf() format specifier that prints out a uint64_t. If your implementation expands this to "llu", but the printf() used at runtime needs "I64u", then that is a bug. What you have described here is yet another reason to distrust msys. If I'm forced to program on Windows, I use Cygwin.linuxyne wrote:PRIu64 is "llu" according to c9x standard. But windows doesn't understand "llu". It understands I64u, but that's non-standard.
Then the documentation available with msys/msys2 is incorrect, as that itself claims that I64u is non-standard.nullplan wrote:That is false.
Right. The msys2 toolchain demonstrates that behaviour - it generates %llu to be used on a system that doesn't understand llu. According to their documentation, %llu is part of c9x standard. So according to your statements, they are blatantly lying.nullplan wrote: PRIu64 is defined as a macro that expands to that printf() format specifier that prints out a uint64_t. If your implementation expands this to "llu", but the printf() used at runtime needs "I64u", then that is a bug.
Sure. It's the toolchain' problem, not the compiler.nullplan wrote: What you have described here is yet another reason to distrust msys. If I'm forced to program on Windows, I use Cygwin.
The only reason why I prefer mingw over Cygwin is, because I couldn't compile single binaries with Cygwin. There was always the need to ship cygwin.dll along. For mingw, the POSIX-Win32 wrappers are statically linked into the binary if you use them, but you can also use the Win32 API directly. Now I have last used Cygwin many years ago, this could have changed, and Cygwin might be able to compile statically since. I had no reason to check it again, because mingw is working (most of the time ) like a charm.nullplan wrote:What you have described here is yet another reason to distrust msys. If I'm forced to program on Windows, I use Cygwin.
No, that part is correct. It is however incorrect to claim that PRIu64 is defined by the standard as "llu". "%llu" is defined by the standard to print an unsigned long long, but uint64_t does not have to be unsigned long long, and unsigned long long does not have to be merely 64 bits.linuxyne wrote:Then the documentation available with msys/msys2 is incorrect, as that itself claims that I64u is non-standard.
So on Windows, w*printf() has a different syntax from *printf()? What fresh hell is this? I presume this is because printf() and wprintf() are provided by different libraries, but then that means that whoever wrote the printf() library failed to add wprintf() to its repertoire. Another reason to use Cygwin (if you can stomach newlib).bzt wrote:The interesting thing is, there seems to be no problems with printf, only with wsprintfW.
Meh. I'd rather ship two files instead of one, than having to deal with a C implementation where parts of the library disagree with other parts. And no, this hasn't changed, as all Cygwin programs need to communicate with each other, and having a DLL allows them to switch out the protocol if need be.bzt wrote:The only reason why I prefer mingw over Cygwin is, because I couldn't compile single binaries with Cygwin. There was always the need to ship cygwin.dll along.
What about the issue of string pasting not working correctly? Even if the contents of the string end up not being useful to the printf() function in question, it is still defined that L"a" "b" "c" should be equal to L"abc", and not end up missing a zero-terminator. But then, bzt never did end up providing the assembly listing GCC generated, so I still don't know what happened to that point.Octocontrabass wrote:So, to sum up this thread, there are no breaking changes in GCC 10.2.0.
The two issues bzt spotted are undefined behavior and an incompatibility caused by trying to mix the mingw printf functions with Microsoft's printf functions. I didn't see any attempts to print a size_t, so I don't think any changes would be necessary aside from removing this part of the makefile.
I built the example code provided by bzt using the same build system and compiler (MSYS2) and was not able to reproduce the issue. I suspect bzt just misread the hexdump.nullplan wrote:What about the issue of string pasting not working correctly?