Considerações adicionais
Ao portar seu código, considere os seguintes pontos:
A seguinte suposição não é mais válida:
#ifdef _WIN32 // Win32 code ... #else // Win16 code ... #endif
No entanto, o compilador de 64 bits define _WIN32 para compatibilidade com versões anteriores.
A seguinte suposição não é mais válida:
#ifdef _WIN16 // Win16 code ... #else // Win32 code ... #endif
Nesse caso, a cláusula else pode representar _WIN32 ou _WIN64.
Tenha cuidado com o alinhamento do tipo de dados. A macro TYPE_ALIGNMENT retorna os requisitos de alinhamento de um tipo de dados. Por exemplo:
TYPE_ALIGNMENT( KFLOATING_SAVE )
== 4 em x86, 8 no processadorTYPE_ALIGNMENT( UCHAR )
Intel Itanium == 1 em todos os lugaresPor exemplo, código de kernel que atualmente tem esta aparência:
ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
provavelmente deve ser alterado para:
ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
Correções automáticas de exceções de alinhamento no modo kernel são desabilitadas para sistemas Intel Itanium.
Tenha cuidado com as operações NOT. Considere o seguinte:
UINT_PTR a; ULONG b; a = a & ~(b - 1);
O problema é que ~(b-1) produz "0x0000 0000 xxxx xxxx" e não "0xFFFF FFFF xxxx xxxx". O compilador não detectará isso. Para corrigir isso, altere o código da seguinte maneira:
a = a & ~((UINT_PTR)b - 1);
Tenha cuidado ao executar operações não assinadas e assinadas. Considere o seguinte:
LONG a; ULONG b; LONG c; a = -10; b = 2; c = a / b;
O resultado é inesperadamente grande. A regra é que, se um dos operandos não estiver assinado, o resultado não será assinado. No exemplo anterior, um é convertido em um valor não assinado, dividido por b e o resultado armazenado em c. A conversão não envolve manipulação numérica.
Como outro exemplo, considere o seguinte:
ULONG x; LONG y; LONG *pVar1; LONG *pVar2; pVar2 = pVar1 + y * (x - 1);
O problema surge porque x não está assinado, o que torna toda a expressão sem sinal. Isso funciona bem, a menos que y seja negativo. Nesse caso, y é convertido em um valor não assinado, a expressão é avaliada usando precisão de 32 bits, dimensionada e adicionada a pVar1. Um número negativo sem sinal de 32 bits se torna um número positivo grande de 64 bits, o que dá o resultado errado. Para corrigir esse problema, declare x como um valor assinado ou digite-o explicitamente para LONG na expressão.
Tenha cuidado ao fazer alocações de tamanho por etapas. Por exemplo:
struct xx { DWORD NumberOfPointers; PVOID Pointers[100]; };
O código a seguir está errado porque o compilador preencherá a estrutura com 4 bytes adicionais para fazer o alinhamento de 8 bytes:
malloc(sizeof(DWORD) + 100*sizeof(PVOID));
O código a seguir está correto:
malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
Não passe
(HANDLE)0xFFFFFFFF
para funções como CreateFileMapping. Em vez disso, use INVALID_HANDLE_VALUE.Use os especificadores de formato adequados ao imprimir uma cadeia de caracteres. Use %p para imprimir ponteiros em hexadecimal. Essa é a melhor opção para imprimir ponteiros. Microsoft Visual C++ dá suporte a %I para imprimir dados polimórficos. O Visual C++ também dá suporte a %I64 para imprimir valores de 64 bits.