This is the mail archive of the cygwin mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Porting to 64 bit Cygwin (was Re: Difference in 32/64-bit curl.)

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

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:


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

  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

    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.



Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

Problem reports:
Unsubscribe info:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]