Дополнительные рекомендации
При переносе кода рассмотрите следующие моменты:
Следующее предположение больше не является допустимым:
#ifdef _WIN32 // Win32 code ... #else // Win16 code ... #endif
Однако 64-разрядный компилятор определяет _WIN32 для обратной совместимости.
Следующее предположение больше не является допустимым:
#ifdef _WIN16 // Win16 code ... #else // Win32 code ... #endif
В этом случае предложение else может представлять _WIN32 или _WIN64.
Будьте осторожны с выравниванием типа данных. Макрос TYPE_ALIGNMENT возвращает требования к выравниванию типа данных. Например:
TYPE_ALIGNMENT( KFLOATING_SAVE )
== 4 в x86, 8 на процессоре Intel ItaniumTYPE_ALIGNMENT( UCHAR )
== 1 вездеНапример, код ядра, который в настоящее время выглядит следующим образом:
ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
может быть изменено на:
ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
Автоматические исправления исключений выравнивания в режиме ядра отключены для систем Intel Itanium.
Будьте осторожны с операциями NOT. Рассмотрим следующее:
UINT_PTR a; ULONG b; a = a & ~(b - 1);
Проблема заключается в том, что ~(b–1) создает "0x0000 0000 xxxx xxxx", а не "0xFFFF FFFF xxxx xxxx". Компилятор не обнаружит это. Чтобы устранить эту проблему, измените код следующим образом:
a = a & ~((UINT_PTR)b - 1);
Будьте осторожны при выполнении неподписанных и подписанных операций. Рассмотрим следующее:
LONG a; ULONG b; LONG c; a = -10; b = 2; c = a / b;
Результат неожиданно велик. Правило заключается в том, что если любой операнду не назначен, результат не указан. В предыдущем примере преобразуется в значение без знака, разделенное на b, и результат, хранящийся в c. Преобразование не включает числовые манипуляции.
В качестве другого примера рассмотрим следующее:
ULONG x; LONG y; LONG *pVar1; LONG *pVar2; pVar2 = pVar1 + y * (x - 1);
Проблема возникает из-за отмены знака x, что делает все выражение без знака. Это работает нормально, если y не является отрицательным. В этом случае y преобразуется в значение без знака, выражение вычисляется с помощью 32-разрядной точности, масштабирования и добавления в pVar1. 32-разрядное отрицательное число без знака становится большим 64-разрядным положительным числом, что дает неправильный результат. Чтобы устранить эту проблему, объявите x как подписанное значение или явно введите его в LONG в выражении.
Будьте осторожны при создании фрагментных выделений размера. Например:
struct xx { DWORD NumberOfPointers; PVOID Pointers[100]; };
Следующий код неправильно, так как компилятор будет заполнять структуру дополнительными 4 байтами, чтобы сделать выравнивание 8-байтов:
malloc(sizeof(DWORD) + 100*sizeof(PVOID));
Следующий код правильный:
malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
Не передайте
(HANDLE)0xFFFFFFFF
в такие функции, как CreateFileMapping. Вместо этого используйте INVALID_HANDLE_VALUE.При печати строки используйте правильные описатели формата. Используйте %p для печати указателей в шестнадцатеричном виде. Это лучший выбор для печати указателей. Microsoft Visual C++ поддерживает %I для печати полиморфных данных. Visual C++ также поддерживает %I64 для печати значений, 64 битов.