Вновь хочется рассказать об очередной 64-битной ошибке, найденной нами в одной из программ. Публиковать в блоге интересные и специфичные ошибки программирования для 64-битных систем постепенно становится хорошей традицией, которой мы постараемся следовать.
Описанная ошибка заслуживает внимания своей простотой и можно сказать простодушностью. Много лет во всех книгах рекомендуют не использовать в коде магические константы, все про это знают, обязательно упоминают в стандартах кодирования и так далее. Но на практике, волшебные числа возникают в различных участках кода вновь и вновь.
Рассмотрим пример вызова функции CreateFileMapping в одном из приложений:
hFileMapping = CreateFileMapping (
(HANDLE) 0xFFFFFFFF,
NULL,
PAGE_READWRITE,
(DWORD) 0,
(DWORD) (szBufIm),
(LPCTSTR) &FileShareNameMap[0]);
Да, да - вы уже правильно догадались. Ошибка заключается в использовании константы 0xFFFFFFFF. Первый аргумент функции CreateFileMapping может иметь значение INVALID_HANDLE_VALUE, объявленное следующим образом:
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
В результате INVALID_HANDLE_VALUE действительно совпадает в 32-битной системе со значением 0xFFFFFFFF. А вот в 64-битной системе в функцию CreateFileMapping будет передано значение 0×00000000FFFFFFFF в результате чего система посчитает аргумент некорректным и вернет код ошибки. Причина в том, что значение 0xFFFFFFFF имеет БЕЗЗАНКОВЫЙ тип (unsigned int). Значение 0xFFFFFFFF не помещается в тип int и поэтому является типом unsigned. Это тонкий момент, на который следует обратить внимание при переходе на 64-битные системы. Поясним его на примере:
void foo(void *ptr)
{
cout << ptr << endl;
}
int _tmain(int, _TCHAR *[])
{
cout << "-1\t\t";
foo((void *)-1);
cout << "0xFFFFFFFF\t";
foo((void *)0xFFFFFFFF);
}
Результат работы 32-битного варианта программы:
-1 FFFFFFFF
0xFFFFFFFF FFFFFFFF
Результат работы 64-битного варианта программы:
-1 FFFFFFFFFFFFFFFF
0xFFFFFFFF 00000000FFFFFFFF
Вы спросите, как все это помнить и как быть уверенным, что подобных ловушек не содержит старый код? Как всегда рекламный ответ - используйте специализированную систему статического анализа Viva64, включенную в состав PVS-Studio.