Weitere Überlegungen

Berücksichtigen Sie beim Portieren Ihres Codes die folgenden Punkte:

  • Die folgende Annahme ist nicht mehr gültig:

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

    Der 64-Bit-Compiler definiert jedoch _WIN32 für die Abwärtskompatibilität.

  • Die folgende Annahme ist nicht mehr gültig:

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

    In diesem Fall kann die else-Klausel _WIN32 oder _WIN64 darstellen.

  • Seien Sie vorsichtig bei der Datentypausrichtung. Das TYPE_ALIGNMENT Makro gibt die Ausrichtungsanforderungen eines Datentyps zurück. Beispiel: TYPE_ALIGNMENT( KFLOATING_SAVE ) == 4 auf x86, 8 auf Intel Itanium-ProzessorTYPE_ALIGNMENT( UCHAR ) == 1 überall

    Beispiel: Kernelcode, der derzeit wie folgt aussieht:

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

    sollte wahrscheinlich in geändert werden:

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

    Automatische Korrekturen von Kernelmodusausnahmen sind für Intel Itanium-Systeme deaktiviert.

  • Seien Sie vorsichtig mit NOT-Vorgängen. Beachten Sie Folgendes:

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

    Das Problem besteht darin, dass ~(b–1) "0x0000 0000 xxxx xxxx" und nicht "0xFFFF FFFF xxxx xxxx" erzeugt. Der Compiler erkennt dies nicht. Um dies zu beheben, ändern Sie den Code wie folgt:

    a = a & ~((UINT_PTR)b - 1);
    
  • Achten Sie darauf, unsignierte und signierte Vorgänge auszuführen. Beachten Sie Folgendes:

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

    Das Ergebnis ist unerwartet groß. Die Regel lautet: Wenn ein Operand nicht signiert ist, ist das Ergebnis nicht signiert. Im vorherigen Beispiel wird a in einen wert ohne Vorzeichen konvertiert, dividiert durch b, und das Ergebnis wird in c gespeichert. Die Konvertierung beinhaltet keine numerische Bearbeitung.

    Betrachten Sie als weiteres Beispiel Folgendes:

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

    Das Problem tritt auf, weil x ohne Vorzeichen ist, wodurch der gesamte Ausdruck unsigniert ist. Dies funktioniert gut, es sei denn, y ist negativ. In diesem Fall wird y in einen wert ohne Vorzeichen konvertiert, der Ausdruck wird mit 32-Bit-Genauigkeit ausgewertet, skaliert und pVar1 hinzugefügt. Eine 32-Bit-Negative Zahl ohne Vorzeichen wird zu einer großen positiven 64-Bit-Zahl, die das falsche Ergebnis liefert. Um dieses Problem zu beheben, deklarieren Sie x als signierten Wert oder geben Sie es explizit in LONG im Ausdruck aus.

  • Seien Sie beim Erstellen von Stückgrößenzuordnungen vorsichtig. Beispiel:

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

    Der folgende Code ist falsch, da der Compiler die Struktur mit zusätzlichen 4 Bytes unterbindet, um die 8-Byte-Ausrichtung vorzunehmen:

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

    Der folgende Code ist richtig:

    malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
    
  • Übergeben (HANDLE)0xFFFFFFFF Sie nicht an Funktionen wie CreateFileMapping. Verwenden Sie stattdessen INVALID_HANDLE_VALUE.

  • Verwenden Sie beim Drucken einer Zeichenfolge die richtigen Formatbezeichner. Verwenden Sie %p, um Zeiger in Hexadezimal zu drucken. Dies ist die beste Wahl zum Drucken von Zeigern. Microsoft Visual C++ unterstützt %I zum Drucken polymorpher Daten. Visual C++ unterstützt auch %I64 zum Drucken von Werten mit 64 Bit.