On Apr 24 14:59, Corinna Vinschen wrote: > On Apr 23 23:56, Christian Franke wrote: > > Possibly a __builtin_va_list related gcc bug. > > This is rather unlikely. That code is shared between Cygwin and > Mingw, and chances are that the bug would have been found already. > > What about a type issue? int vs. long?
For clearness I decided to add a quick lecture. Hope that's ok. The Cygwin x86_64 toolchain is using the LP64(*) data model. That means, in contrast to Windows, which uses an LLP64(*) data model, sizeof(long) != sizeof(int), just as on Linux. For comparison: Cygwin Windows Cygwin Linux x86_64 Linux Windows x86_64 i686 sizeof(int) 4 4 4 sizeof(long) 4 4 8 sizeof(size_t) 4 8 8 sizeof(void*) 4 8 8 This difference can result in interesting problems, especially when using Win32 functions, especially when using pointers to Windows datatypes like LONG, ULONG, DWORD. Given that Windows is LLP64, all of these are 4 byte in size, while `long' on Cygwin is 8 bytes. Take the example ReadFile: ReadFile (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); In the 32 bit Cygwin and Mingw environments, as well as in the 64 bit Mingw environment, it is no problem to substitute DWORD with unsigned long: unsigned long number_of_bytes_read; [...] ReadFile (fhdl, buf, buflen, &number_of_bytes_read, NULL); However, in 64 bit Cygwin, using LP64, number_of_bytes_read is 8 bytes in size. But ReadFile expects a pointer to a 4 byte type. So the function will only change the lower 4 bytes of number_of_bytes_read, while the content of the upper 4 bytes is undefined. Here are a few donts which may help porting applications from the ILP32 to the new LP64 data model. Note that this is not a Cygwin-only problem. Many Linux applications suffered the same somewhat liberal handling of datatypes when x86_64 was new. - DON'T mix up int and long in printf/scanf. This: int i; long l; printf ("%d %ld\n", l, i); may not print what you think it should. - DON'T mix int and long pointers. int *ip = (int *) &my_long; /* Uh oh! */ - DON'T mix int and pointers at all! THis will NOT work as expected anymore: void *ptr; printf ("Pointer value is %x\n", (int) ptr); - DON'T use functions returning pointers without declaration. For instance printf ("Error message is: %s\n", strerror (errno)); This code will CRASH, unless you included string.h. The implicit rule in C is that an undeclared function is of type int. But int is 4 byte and pointers are 8 byte, so the string pointer given to printf is missing the upper 4 bytes. Hilarity ensues ;) - DON'T use C base types together with Win32 functions. Keep in mind that DWORD, LONG, ULONG are *not* the same as long and unsigned long. Try to use only Win32 datatypes in conjunction with Win32 API function calls to avoid type problems. - DON'T mix Windows dataypes with POSIX type-specific MIN/MAX values. unsigned long l_max = ULONG_MAX; /* That's right. */ ULONG w32_biggest = ULONG_MAX; /* Hey, wait! What? */ ULONG w32_biggest = UINT_MAX; /* Ok. */ Always keep in mind that ULONG (or DWORD) != unsigned long but rather == unsigned int now. HTH, Corinna (*) http://en.wikipedia.org/wiki/LLP64#64-bit_data_models -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple