26

これを読みまし た アライメントについていつ心配する必要がありますか? しかし、次の例のように、placement new 演算子によって返される整列されていないポインターについて心配する必要があるかどうかはまだわかりません。

class A {
public:
   long double a;
   long long b;
   A() : a(1.3), b(1234) {}
};

char buffer[64];

int main() {
   // (buffer + 1) used intentionally to have wrong alignment
   A* a = new (buffer + 1) A(); 
   a->~A();
}

__alignof(A) == 4、 に(buffer + 1)位置合わせされていません4。しかし、すべて正常に動作します - 完全な例はこちら: http://ideone.com/jBrk8

これがアーキテクチャに依存する場合、私は使用しています: linux/powerpc/g++ 4.xx

[更新] この質問を投稿した直後に、次の記事を読みました: http://virtrev.blogspot.de/2010/09/memory-alignment-theory-and-c-examples.html。おそらく、私の場合の唯一の欠点はパフォーマンスの低下でしょう。

4

5 に答える 5

23

バッファーでplacement newを呼び出すと、次のようになります。

A *a = new (buf) A;

void* operator new (std::size_t size, void* ptr) noexcept次で定義されている組み込みを呼び出しています。

18.6.1.3 配置フォーム [new.delete.placement]

これらの関数は予約済みです。C++ プログラムは、標準 C++ ライブラリ (17.6.4) のバージョンを置き換える関数を定義できません。(3.7.4) の規定は、演算子 new および演算子削除のこれらの予約配置形式には適用されません。

void* operator new(std::size_t size, void* ptr) noexcept;
戻り値: ptr.
備考: 意図的に他のアクションを実行しません。

(3.7.4)の規定には、返されたポインターが適切に整列されている必要があることが含まれているため、ポインターが渡された場合void* operator new (std::size_t size, void* ptr) noexcept、非整列ポインターを返すことは問題ありません。

5.3.4 新しい [expr.new]

[14] 注: 割り当て関数が null 以外の値を返す場合、それは、オブジェクト用のスペースが予約されているストレージのブロックへのポインターでなければなりません。ストレージのブロックは、適切に位置合わせされ、要求されたサイズであると想定されます。

したがって、アライメントされていないストレージをplacement-new式に渡すと、ストレージがアライメントされているという仮定に違反し、結果はUBになります。


実際、上記のプログラムで(after ) に置き換えるlong long bと、プログラムは予想どおり segfault します。__m128 b#include <xmmintrin.h>

于 2012-08-02T16:57:47.350 に答える
11

すべてが機能しているように見えても、実際に機能するとは限りません。

C++ は、機能するために何が必要かを定義する仕様です。コンパイラは、必要でないものを機能させることもできます。それが「未定義の動作」の意味です。何かが起こる可能性があるため、コードは移植できなくなります。

C++ では、これが機能する必要はありません。したがって、これが機能しないコンパイラーにコードを持ち込んだとしても、もはや C++ を責めることはできません。言語を誤用したのはあなたのせいです。

于 2012-08-02T16:22:43.770 に答える
4

はい、それはすべてアーキテクチャに依存し、おそらくコンパイラの最適化フラグにも依存します。A b = a;あなたがそうするか、いくつかのmovdqaopsにコンパイルされてプログラムがクラッシュする他のランダムアクセスまで、それはすべて正常に機能します。

于 2012-08-02T16:22:58.647 に答える
4

一部のプロセッサはこれで確実に爆発します (たとえば、sparc)、まったく気にしないプロセッサもあれば、遅いプロセッサもあります。C++ は、reinterpret_cast などと同じように、自分が何をしているのか (またはしていないのか) を知っていることを前提としています。

于 2012-08-02T16:26:20.957 に答える
3

ちょっとグーグルで調べてみると、powerpc の gcc には、アラインされていないアクセスがシステムによって処理されるかどうかをコンパイラに伝えるオプションがあることがわかります。

どちらの場合も、そのプラットフォームでのアラインされていないアクセスは非常に遅くなり、可能な限り回避する必要があると思います。

于 2012-08-02T16:26:22.347 に答える