Partilhar via


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 lugares

    Por 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.