Dela via


Ytterligare överväganden

Tänk på följande när du porterar koden:

  • Följande antagande är inte längre giltigt:

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

    64-bitarskompilatorn definierar dock _WIN32 för bakåtkompatibilitet.

  • Följande antagande är inte längre giltigt:

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

    I det här fallet kan else-satsen representera _WIN32 eller _WIN64.

  • Var försiktig med justering av datatyp. Makrot TYPE_ALIGNMENT returnerar justeringskraven för en datatyp. Till exempel: TYPE_ALIGNMENT( KFLOATING_SAVE ) == 4 på x86, 8 på Intel Itanium-processorTYPE_ALIGNMENT( UCHAR ) == 1 överallt

    Till exempel kernelkod som för närvarande ser ut så här:

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

    bör förmodligen ändras till:

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

    Automatiska korrigeringar av undantag för kernellägesjustering inaktiveras för Intel Itanium-system.

  • Var försiktig med NOT-åtgärder. Tänk på följande:

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

    Problemet är att ~(b–1) producerar "0x0000 0000 xxxx xxxx" och inte "0xFFFF FFFF xxxx xxxx". Kompilatorn identifierar inte detta. Åtgärda detta genom att ändra koden på följande sätt:

    a = a & ~((UINT_PTR)b - 1);
    
  • Var försiktig med att utföra osignerade och signerade åtgärder. Tänk på följande:

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

    Resultatet är oväntat stort. Regeln är att om någon av operanderna är osignerade, är resultatet osignerat. I föregående exempel konverteras en till ett osignerat värde, dividerat med b och resultatet som lagras i c. Konverteringen innebär ingen numerisk manipulering.

    Som ett annat exempel bör du tänka på följande:

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

    Problemet uppstår eftersom x är osignerat, vilket gör hela uttrycket osignerat. Detta fungerar bra om inte y är negativt. I det här fallet konverteras y till ett osignerat värde, uttrycket utvärderas med 32-bitars precision, skalas och läggs till i pVar1. Ett 32-bitars osignerat negativt tal blir ett stort 64-bitars positivt tal, vilket ger fel resultat. Åtgärda problemet genom att deklarera x som ett signerat värde eller uttryckligen skriva det till LONG- i uttrycket.

  • Var försiktig när du gör bitstorleksallokeringar. Till exempel:

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

    Följande kod är fel eftersom kompilatorn fyller strukturen med ytterligare 4 byte för att göra justeringen på 8 byte:

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

    Följande kod är korrekt:

    malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
    
  • Skicka inte (HANDLE)0xFFFFFFFF till funktioner som CreateFileMapping. Använd i stället INVALID_HANDLE_VALUE.

  • Använd rätt formatspecificerare när du skriver ut en sträng. Använd %p för att skriva ut pekare i hexadecimalt. Det här är det bästa valet för att skriva ut pekare. Microsoft Visual C++ stöder %I för att skriva ut polymorfa data. Visual C++ stöder också %I64 för att skriva ut värden som är 64 bitar.