Problems of 64-bit code in real programs: magic constants

28.08.2009 Andrey Karpov

I would like to tell you about one more 64-bit error we have found in some program. It becomes a good tradition to publish information about interesting and specific programming errors for 64-bit systems and we will try to follow it.

The error described deserves attention because of its simplicity or even ingenuousness. It has been recommended in all the books for many years not to use magic constants in code. Everyone knows about it and mentions it in coding standards. But in practice magic numbers appear in various code sections again and again.

Let's consider an example of CreateFileMapping function's call in some application:

hFileMapping = CreateFileMapping (
    (HANDLE) 0xFFFFFFFF,
    NULL,
    PAGE_READWRITE,
    (DWORD) 0,
    (DWORD) (szBufIm),
    (LPCTSTR) &FileShareNameMap[0]);

Right - you have guessed it. The error is in using constant 0xFFFFFFFF. The first argument of CreateFileMapping function may have value INVALID_HANDLE_VALUE defined in the following way:

#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)

As a result, INVALID_HANDLE_VALUE does coincide with 0xFFFFFFFF value in a 32-bit system. But in a 64-bit system 0×00000000FFFFFFFF value will be put into CreateFileMapping function and as a result the system will consider the argument incorrect and return the errors' code. The cause is that 0xFFFFFFFF value has UNSIGNED type (unsigned int). 0xFFFFFFFF value does not fit into int type and that's why has unsigned type. It is a subtle point you should pay attention to when performing migration on 64-bit systems. Let's illustrate it by an example:

void foo(void *ptr)
{
   cout << ptr << endl;
}
int _tmain(int, _TCHAR *[])
{
   cout << "-1\t\t";
   foo((void *)-1);
   cout << "0xFFFFFFFF\t";
   foo((void *)0xFFFFFFFF);
}

The result in the 32-bit version of the program:

-1              FFFFFFFF
0xFFFFFFFF      FFFFFFFF

The result in the 64-bit version of the program:

-1              FFFFFFFFFFFFFFFF
0xFFFFFFFF      00000000FFFFFFFF

You will ask how one can remember this all and how one can be sure that the old code does not contain such traps. As usual here you are an ad-answer - use a specialized system of static analysis Viva64 included into PVS-Studio. :)