次の方法で共有


その他の考慮事項

コードを移植するときは、次の点を考慮してください。

  • 次の前提は無効です。

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

    ただし、64 ビット コンパイラは下位互換性のために_WIN32を定義します。

  • 次の前提は無効です。

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

    この場合、else 句は_WIN32または_WIN64を表すことができます。

  • データ型の配置には注意してください。 TYPE_ALIGNMENT マクロは、データ型の配置要件を返します。 例: x86 では TYPE_ALIGNMENT( KFLOATING_SAVE ) == 4、Intel Itanium プロセッサでは 8TYPE_ALIGNMENT( UCHAR ) == 1

    例として、現在次のようなカーネル コードがあります。

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

    おそらく次のように変更する必要があります。

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

    Intel Itanium システムでは、カーネル モードアラインメント例外の自動修正が無効になります。

  • NOT 操作には注意してください。 次の点を考慮してください。

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

    問題は、~(b–1) が "0xFFFF FFFF xxxx xxxx" ではなく "0x0000 0000 xxxx xxxx" を生成することです。 コンパイラはこれを検出しません。 これを修正するには、次のようにコードを変更します。

    a = a & ~((UINT_PTR)b - 1);
    
  • 署名されていない操作と署名された操作を実行する場合は注意してください。 次の点を考慮してください。

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

    結果が予期せず大きくなります。 ルールは、いずれかのオペランドが符号なしの場合、結果は符号なしになります。 前の例では、a は符号なし値に変換され、b で除算され、結果は c に格納されています。 変換には数値操作は必要ありません。

    別の例として、次の点を考えてみましょう。

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

    この問題は、x が符号なしであるために発生します。これにより、式全体が符号なしになります。 これは、y が負の値でない限り正常に動作します。 この場合、y は符号なし値に変換され、式は 32 ビット精度を使用して評価され、スケーリングされ、pVar1 に追加されます。 32 ビット符号なし負の数は、大きな 64 ビットの正の数になり、結果が間違っています。 この問題を解決するには、x を符号付き値として宣言するか、明示的に型キャストして式の LONG します。

  • 断片的なサイズの割り当てを行うときは注意してください。 例えば:

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

    次のコードは間違っています。これは、コンパイラが構造体に 4 バイトを追加して 8 バイトのアラインメントを行うためです。

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

    次のコードは正しいです。

    malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
    
  • CreateFileMappingなどの関数に (HANDLE)0xFFFFFFFF渡さないでください。 代わりに、INVALID_HANDLE_VALUEを使用します。

  • 文字列を印刷するときは、適切な書式指定子を使用します。 ポインターを 16 進数で出力するには、%p を使用します。 これはポインターの印刷に最適な選択肢です。 Microsoft Visual C++ では、ポリモーフィック なデータを印刷する %I がサポートされています。 Visual C++ では、64 ビットの値を出力する %I64 もサポートされています。