C コンパイラのパッキングに関する問題
パッキング レベルは、MIDL コンパイラと Microsoft C/C++ コンパイラの両方の型のメモリ レイアウトにも同じように影響します。 VC++ またはプラットフォーム ソフトウェア開発キット (SDK) によって定義されたビルド環境などの Microsoft ビルド環境では、MIDL コンパイラと C/C++ コンパイラの既定のパッキング レベルは同じです。32 ビットおよび 64 ビット Windows ビルド環境の既定のパッキング レベルは 8 です。
自然な配置
メモリ内の型の場合、既定の配置は自然な配置と同じです。
- short、float、__int64などの基本型とポインターは、その表現がサイズの剰余であるアドレスから始まる場合、自然に配置されます。 現在サポートされているすべての基本型のサイズは 1、2、4、または 8 です。 ポインターのサイズは、32 ビット環境では 4、64 ビット環境では 8 です。
- 複合型は、各コンポーネントが型の先頭に対して自然に配置され、コンポーネント間に不要なギャップ (パディング) がない場合は、自然に整列されます。 フィールドや要素などの複合コンポーネントは、ポインターまたは基本型のコンポーネントに再帰されます。
この動作を覚えておくのに役立つ簡単な規則は、型の自然な配置は、そのコンポーネントの最大の配置と等しいということです。
C や C++ などの言語の型の配置とメモリ サイズと、演算子 sizeof() で表される IDL の間には接続があります。 サイズは、アラインメントの倍数です (型にまたがる最小限の倍数)。 これは、メモリ内の配列表現に従います。
不整合なデータにアクセスすると、一部のシステムで例外が発生する可能性があるため、自然な配置が重要です。 データは、配置が間違っている場合に安全な操作用にマークできますが、通常は、一部のプラットフォームで相当な速度のペナルティが発生する可能性があります。
Note
メモリでは、n の自然なアラインメントを持つ型のオブジェクトは、n の倍数であるアドレスに配置されると、正しく配置されます。
パッキングとアラインメント
型の自然な配置よりも大きいパッキング レベルを指定しても、型の配置は変更されません。 パッキング レベルを自然な配置よりも小さく指定すると、型の配置がパッキング レベルに減ります。 その結果、パックされた型は、不整合を引き起こすことなく、パッキング レベルの倍数 (アラインメントの減少) であるアドレスにメモリに配置される可能性があります。 これは、単純型とコンポーネント型の両方に影響します。 複合型の場合、コンポーネントの配置が減少すると、コンポーネントの適切な配置に必要なパディングのサイズが変更され、型のサイズが小さくなる可能性があるため、型の内部レイアウトが影響を受ける可能性があります。
この動作を覚えておくのに役立つ簡単なルールは、パックされた型の新しい配置が、パッキング レベルとその自然な配置の小さい方であるということです。 型のサイズは、新しい配置の倍数です。 sizeof() 演算子は、パックされた型の縮小サイズを返します。
たとえば、パッキング レベル 2 の場合、長いは 2 に揃えられます。したがって、自然な配置の場合と同様に、4 の倍数であるアドレスだけでなく、任意の偶数のアドレスに配置できます。 短くて長く、2で詰められた構造は、自然なアライメントに必要な短い長さと次の長さとの間の内部ギャップを必要としません。そのため、構造体が 2 に配置されるだけでなく、サイズも 8 から 6 に縮小されます。
たとえば、1 バイト文字、長さ 4 バイトの整数、1 バイト文字で構成される複合型を考えてみましょう。
struct mystructtype
{
char c1; /* requires 1 byte */
/* 3 bytes of padding with natural alignment only */
long l2; /* requires 4 bytes */
char c3; /* requires 1 byte */
/* 3 bytes of padding with natural alignment only */
} mystruct;
この構造は自然に4に整列し、12の自然なサイズを有する。
パッキング レベル 4 以上の場合、構造体 mystruct は 4 に揃え、 sizeof(struct mystructtype)
12 に等しくなります。 4 の倍数ではないアドレスのメモリ内に配置されている場合、構造体は不整合になります。
梱包レベル 2 の場合、構造体は 2 に揃え、サイズは 8 です。 レベル 2 でパックされた構造体は、2 の倍数ではないアドレスのメモリに配置されている場合、不整合になります。
梱包レベル 1 の場合、構造体は 1 に揃え、サイズは 6 です。 レベル 1 が詰まった構造は、ミスアライメント障害を引き起こさずに、任意の場所に配置できます。
関連トピック