Considérations supplémentaires

Lors du portage de votre code, tenez compte des points suivants :

  • L’hypothèse suivante n’est plus valide :

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

    Toutefois, le compilateur 64 bits définit _WIN32 pour la compatibilité descendante.

  • L’hypothèse suivante n’est plus valide :

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

    Dans ce cas, la clause else peut représenter _WIN32 ou _WIN64.

  • Soyez prudent avec l’alignement du type de données. La macro TYPE_ALIGNMENT retourne les exigences d’alignement d’un type de données. Par exemple : TYPE_ALIGNMENT( KFLOATING_SAVE ) == 4 sur x86, 8 sur le processeurTYPE_ALIGNMENT( UCHAR ) Intel Itanium == 1 partout

    Par exemple, le code du noyau qui ressemble actuellement à ceci :

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

    doit probablement être remplacé par :

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

    Les correctifs automatiques des exceptions d’alignement en mode noyau sont désactivés pour les systèmes Intel Itanium.

  • Soyez prudent avec les opérations NOT. Tenez compte des éléments suivants :

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

    Le problème est que ~(b–1) produit « 0x0000 0000 xxxx xxxx » et non « 0xFFFF FFFF xxxx xxxx ». Le compilateur ne détecte pas cela. Pour résoudre ce problème, modifiez le code comme suit :

    a = a & ~((UINT_PTR)b - 1);
    
  • Soyez prudent en effectuant des opérations non signées et signées. Tenez compte des éléments suivants :

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

    Le résultat est d’une ampleur inattendue. La règle est que si l’un des opérandes n’est pas signé, le résultat n’est pas signé. Dans l’exemple précédent, a est converti en valeur non signée, divisée par b, et le résultat est stocké dans c. La conversion n’implique aucune manipulation numérique.

    Comme autre exemple, considérez les éléments suivants :

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

    Le problème se produit parce que x n’est pas signé, ce qui rend l’expression entière non signée. Cela fonctionne bien, sauf si y est négatif. Dans ce cas, y est converti en valeur non signée, l’expression est évaluée à l’aide d’une précision 32 bits, mise à l’échelle et ajoutée à pVar1. Un nombre négatif non signé 32 bits devient un grand nombre positif de 64 bits, ce qui donne un résultat incorrect. Pour résoudre ce problème, déclarez x en tant que valeur signée ou saisissez-la explicitement en LONG dans l’expression.

  • Soyez prudent lorsque vous effectuez des allocations de taille fragmentaire. Par exemple :

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

    Le code suivant est incorrect, car le compilateur va compléter la structure avec 4 octets supplémentaires pour effectuer l’alignement de 8 octets :

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

    Le code suivant est correct :

    malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
    
  • Ne passez pas à des (HANDLE)0xFFFFFFFF fonctions telles que CreateFileMapping. Utilisez plutôt INVALID_HANDLE_VALUE.

  • Utilisez les spécificateurs de format appropriés lors de l’impression d’une chaîne. Utilisez %p pour imprimer des pointeurs en hexadécimal. Il s’agit du meilleur choix pour imprimer des pointeurs. Microsoft Visual C++ prend en charge %I pour imprimer des données polymorphes. Visual C++ prend également en charge %I64 pour imprimer des valeurs de 64 bits.