また、glibc malloc() がこれを行うかどうかも知りたいです。
4 に答える
あなたが構造を持っていると仮定します。
struct S {
short a;
int b;
char c, d;
};
アラインメントがないと、次のようにメモリに配置されます(32ビットアーキテクチャを想定)。
0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d| bytes
| | | words
問題は、一部のCPUアーキテクチャでは、メモリから4バイト整数をロードする命令がワード境界でのみ機能することです。したがって、プログラムはb
別々の命令でそれぞれの半分をフェッチする必要があります。
しかし、メモリが次のようにレイアウトされている場合:
0 1 2 3 4 5 6 7 8 9 A B
|a|a| | |b|b|b|b|c|d| | |
| | | |
そうすれば、へのアクセスb
が簡単になります。(欠点は、パディングバイトのためにより多くのメモリが必要になることです。)
データ型が異なれば、アライメント要件も異なります。char
1バイトにアラインされ、short
2バイトにアラインされ、4バイトタイプ(int
、、、float
および32ビットシステムのポインタ)が4バイトにアラインされるのが一般的です。
malloc
C標準では、任意のデータ型に適切に配置されたポインタを返す必要があります。
x86-64上のglibcmalloc
は、16バイトに整列されたポインターを返します。
アライメント要件は、どのタイプにどのアドレス オフセットを割り当てることができるかを指定します。これは完全に実装に依存しますが、通常はワード サイズに基づいています。たとえば、一部の 32 ビット アーキテクチャでは、すべてのint
変数が 4 の倍数で始まる必要があります。一部のアーキテクチャでは、配置要件が絶対的です。他のもの (x86 など) では、それらを無視すると、パフォーマンスが低下するだけです。
malloc
アライメント要件に適したアドレスを返す必要があります。つまり、返されたアドレスは、任意の型のポインターに割り当てることができます。C99 §7.20.3 (メモリ管理機能) から:
割り当てが成功した場合に返されるポインターは、任意の型のオブジェクトへのポインターに割り当てられ、割り当てられた空間内のそのようなオブジェクトまたはそのようなオブジェクトの配列にアクセスするために使用されるように適切に整列されます (空間が明示的に割り当て解除されるまで)。 .
(特定のハードウェアまたはライブラリに対して) 特定のメモリ アライメントが必要な場合は、_aligned_malloc()
やなどの移植性のないメモリ アロケータを確認できますmemalign()
。これらは「移植可能な」インターフェースの背後で簡単に抽象化できますが、残念ながら非標準です。
malloc()
ドキュメントには次のように記載されています。
[...] the allocated memory that is suitably aligned for any kind of variable.
これは、C/C++ で行うほとんどすべてに当てはまります。ただし、他の人が指摘したように、多くの特殊なケースが存在し、特定の調整が必要です。たとえば、Intel プロセッサは 256 ビット タイプをサポートして__m256
いますmalloc()
。
同様に、ページングされるデータにメモリ バッファを割り当てたい場合 (mmap()
などによって返されるアドレスと同様)、非常に大きなアラインメントが必要になる可能性があり、malloc()
常にアラインされたバッファを返す場合、多くのメモリを浪費することになります。そのような境界。
Linux またはその他の Unix システムでは、次のposix_memalign()
関数を使用することをお勧めします。
int posix_memalign(void **memptr, size_t alignment, size_t size);
これは、そのようなニーズに使用したい最新の機能です。