Partilhar via


Considerações adicionais

Ao portar seu código, considere os seguintes pontos:

  • O seguinte pressuposto já não é válido:

    #ifdef _WIN32 // Win32 code
        ...
    #else         // Win16 code
        ...
    #endif
    

    No entanto, o compilador de 64 bits define _WIN32 para compatibilidade com versões anteriores.

  • O seguinte pressuposto já não é válido:

    #ifdef _WIN16 // Win16 code
        ...
    #else         // Win32 code
        ...
    #endif
    

    Neste 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 no x86, 8 no processador Intel ItaniumTYPE_ALIGNMENT( UCHAR ) == 1 em todos os lugares

    Como exemplo, o código do kernel que atualmente se parece com isto:

    ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
    

    provavelmente deve ser alterado para:

    ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
    

    As correções automáticas de exceções de alinhamento do modo kernel estão desativadas para sistemas Intel Itanium.

  • Tenha cuidado com as operações NÃO. 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 detetará 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, a é 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 não assinada. 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 ao pVar1. Um número negativo não assinado de 32 bits torna-se um grande número positivo 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 fragmentadas. Por exemplo:

    struct xx {
       DWORD NumberOfPointers;
       PVOID Pointers[100];
    };
    

    O código a seguir está errado porque o compilador irá 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. Esta é a melhor escolha para ponteiros de impressão. Microsoft Visual C++ suporta %I para imprimir dados polimórficos. Visual C++ também suporta %I64 para imprimir valores que são 64 bits.