Consideraciones adicionales

Al migrar el código, tenga en cuenta los siguientes puntos:

  • La suposición siguiente ya no es válida:

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

    Sin embargo, el compilador de 64 bits define _WIN32 para la compatibilidad con versiones anteriores.

  • La suposición siguiente ya no es válida:

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

    En este caso, la cláusula else puede representar _WIN32 o _WIN64.

  • Tenga cuidado con la alineación del tipo de datos. La macro TYPE_ALIGNMENT devuelve los requisitos de alineación de un tipo de datos. Por ejemplo: TYPE_ALIGNMENT( KFLOATING_SAVE ) == 4 en x86, 8 en procesadorTYPE_ALIGNMENT( UCHAR ) Intel Itanium == 1 en todas partes

    Por ejemplo, el código de kernel que tiene el siguiente aspecto:

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

    probablemente debe cambiarse a:

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

    Las correcciones automáticas de excepciones de alineación en modo kernel están deshabilitadas para los sistemas Intel Itanium.

  • Tenga cuidado con las operaciones NOT. Tenga en cuenta lo siguiente.

    UINT_PTR a; 
    ULONG b;
    a = a & ~(b - 1);
    

    El problema es que ~(b–1) produce "0x0000 0000 xxxx xxxx" y no "0xFFFF FFFF xxxx xxxx". El compilador no lo detectará. Para corregirlo, cambie el código de la siguiente manera:

    a = a & ~((UINT_PTR)b - 1);
    
  • Tenga cuidado de realizar operaciones sin firmar y firmadas. Tenga en cuenta lo siguiente.

    LONG a;
    ULONG b;
    LONG c;
    
    a = -10;
    b = 2;
    c = a / b;
    

    El resultado es inesperadamente grande. La regla es que si cualquiera de los operandos no tiene signo, el resultado no tiene signo. En el ejemplo anterior, se convierte en un valor sin signo, dividido por b y el resultado almacenado en c. La conversión no implica ninguna manipulación numérica.

    Como otro ejemplo, tenga en cuenta lo siguiente:

    ULONG x;
    LONG y;
    LONG *pVar1;
    LONG *pVar2;
    
    pVar2 = pVar1 + y * (x - 1);
    

    El problema surge porque x no tiene signo, lo que hace que toda la expresión no esté firmada. Esto funciona bien a menos que y sea negativo. En este caso, y se convierte en un valor sin signo, la expresión se evalúa con precisión de 32 bits, escalado y agregado a pVar1. Un número negativo de 32 bits sin signo se convierte en un número positivo de 64 bits grande, lo que da el resultado incorrecto. Para corregir este problema, declare x como un valor con signo o escriba explícitamente a LONG en la expresión.

  • Tenga cuidado al realizar asignaciones de tamaño por etapas. Por ejemplo:

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

    El código siguiente es incorrecto porque el compilador rellenará la estructura con un adicional de 4 bytes para realizar la alineación de 8 bytes:

    malloc(sizeof(DWORD) + 100*sizeof(PVOID));
    

    El código siguiente es correcto:

    malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
    
  • No pase (HANDLE)0xFFFFFFFF a funciones como CreateFileMapping. En su lugar, use INVALID_HANDLE_VALUE.

  • Use los especificadores de formato adecuados al imprimir una cadena. Use %p para imprimir punteros en hexadecimal. Esta es la mejor opción para imprimir punteros. Microsoft Visual C++ admite %I para imprimir datos polimórficos. Visual C++ también admite %I64 para imprimir valores de 64 bits.