31

経験豊富なプログラマーのほとんどは、データの配置がプログラムのパフォーマンスにとって重要であることを知っています。必要以上に大きなサイズのバッファを割り当て、アラインされたポインタを begin として使用するプログラムを書いたプログラマを見たことがあります。私のプログラムでそれを行うべきか疑問に思っています.C++の新しい操作によって返されるアドレスのアライメントが保証されるかどうかはわかりません。だから私はテストするための小さなプログラムを書きました

for(size_t i = 0; i < 100; ++i) {
    char *p = new char[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
    short *p = new short[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
    float *p = new float[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
system("pause");

私が使用しているコンパイラは Visual C++ Express 2008 です。新しい操作が返すすべてのアドレスが整列されているようです。しかし、よくわかりません。だから私の質問は: 保証はありますか? 彼らが保証を持っているなら、私は自分自身を調整する必要はありません。

4

6 に答える 6

27

アライメントには、標準 (3.7.3.1/2) による次の保証があります。

返されたポインタは、適切に位置合わせされ、任意の完全なオブジェクト型のポインタに変換され、割り当てられたストレージ内のオブジェクトまたは配列にアクセスするために使用されます (対応する割り当て解除関数の呼び出しによってストレージが明示的に割り当て解除されるまで)。 .

編集:保証が保持されない gcc/glibcのバグを強調してくれたtimdayに感謝します。

編集 2 : ベンのコメントは興味深いエッジ ケースを強調しています。割り当てルーチンの要件は、標準で提供されているもののみです。アプリケーションに独自のバージョンがある場合、結果についてそのような保証はありません。

于 2009-02-03T10:09:40.457 に答える
17

これは遅い回答ですが、Linux の状況を明確にするためだけに - 64 ビット システムでは、メモリは常に 16 バイトで整列されます。

http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html

GNU システムで malloc または realloc によって返されるブロックのアドレスは、常に 8 (または 64 ビット システムでは 16) の倍数です。

newオペレータはmalloc内部的にコールするため( を参照)./gcc/libstdc++-v3/libsupc++/new_op.cc、これは にも適用さnewれます。

基本的に定義 mallocの一部である実装は、x86-32 および x86-64 システムでそれぞれ 32 ビット = 4 バイトおよび 64 ビット = 8 バイトであると定義されています。glibcMALLOC_ALIGNMENT2*sizeof(size_t)size_t

$ cat ./glibc-2.14/malloc/malloc.c:
...
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif
...
#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
...
#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGNMENT       (2 * SIZE_SZ)
#endif
于 2012-05-16T21:47:31.293 に答える
8

ちなみに、MS のドキュメントでは、16 バイトでアラインされた malloc/new リターン アドレスについて言及されていますが、実験ではそうではありません。たまたまプロジェクトに 16 バイトのアラインメントが必要になり (拡張命令セットでメモリ コピーを高速化するため)、最終的には独自のアロケータを作成することにしました...

于 2009-02-03T12:11:37.187 に答える
5

プラットフォームの new/new[] 演算子は、基本的なデータ型 (double、float など) で適切に機能するように、十分なアラインメントを持つポインターを返します。少なくとも、賢明な C++ コンパイラ + ランタイムはそれを行う必要があります。

SSE のような特別なアラインメント要件がある場合は、特別なaligned_malloc 関数を使用するか、独自にロールすることをお勧めします。

于 2009-02-03T10:28:44.680 に答える
4

私は、アラインメントを使用して奇数ビットを解放し、自分で使用できるようにするシステムに取り組みました!

彼らは奇数ビットを使用して、仮想メモリ システムを実装しました。

ポインターに奇数ビットが設定されている場合、それを使用して、データ自体ではなくデータベースからデータを取得するための情報を (奇数ビットを差し引いて) 指していることを示します。

私は、これは、それ自体の利益のために巧妙であるとは言えない、特に厄介なコーディングだと思いました!!

トニー

于 2009-02-03T11:12:29.800 に答える