2010-12-12 12 views
12

アライメントされた型または構造体を値渡しで渡すことは、一部の実装では機能しません。これにより、STLコンテナが破損します。これは、メソッドの一部(サイズ変更など)が値で引数を取るためです。アライメントされた型と値による引数の受け渡し

Visual Studio 2008でいくつかのテストを実行し、値の受け渡しがいつどのように失敗するかは完全にはわかりません。私の主な関心事は、機能fooです。それはうまくいくようですが、それはインライン展開や他の偶然の結果かもしれませんか?署名をに変更するとどうなりますかvoid foo(const __m128 &)

あなたのご意見をいただければ幸いです。ありがとうございました。

struct A 
{ 
    __m128 x; 
    int n; 
}; 

void foo(__m128); 
void bar(A); 

void f1() 
{ 
    // won't compile 
    // std::vector<A> vec1(3); 

    // compiles, but fails at runtime when elements are accessed 
    std::vector<__m128> vec2(3); 

    // this seems to work. WHY??? 
    std::vector<__m128, some_16_byte_aligned_allocator<__m128> > vec3(3); 

    __m128 x; 
    A a; 

    // passed by value, is it OK? 
    foo(x); 

    // won't compile 
    //bar(a); 
} 

EDIT。 STLは、値渡しの問題が残っているため、アラインメントされたアロケータでも失敗します。このリンクpass __m128 by value

+0

コンパイルエラー/警告は何ですか?私は「仮パラメータ...整列しない」のようなものを仮定していますか? – celion

+0

これは私が得るものです。エラーC2719: 'unnamed-parameter':仮引数__declspec(align('16 '))はアライメントされません – watson1180

+0

x64では、関数の引数は16バイトのアライメントをサポートしています。私はそれがあなたの直面する問題を解決するわけではないことを知っていますが、ちょっと、何よりもわずかに優れています。 ;) – jalf

答えて

2

見つかり

私は、一般的にこれを行うための唯一の安全な方法は、参照によって渡すことだと思います。一部のプラットフォーム(例:Xbox 360)は、ベクトル引数をレジスタに渡すことをサポートしていますが、x86ではこれが可能ではないと考えています。

std::vectorの場合は、割り当てられたメモリが16バイトにアライメントされていることを確認する必要があります。そうしないと、整列していないベクトルに対してほとんどの操作を実行しようとするとクラッシュします。

複数のプラットフォームをサポートしている場合は、typedefなどの安全なプランを使用してください。

typedef const MyVector& MyVectorParameter; 

次に、値渡しパスをサポートするプラットフォーム上でtypedefを変更できます。

+0

アロケータヘルプをstd :: vector <__m128>に置き換えても、std :: vector はまだコンパイルされません。 – watson1180

+0

'sizeof(A)'をチェックしましたか? 16バイトの倍数ではない場合、ベクトルによって割り当てられた配列記憶域の後続の要素は、記憶域の先頭が整列していても整列されません。 –

+0

プラットフォームのAのサイズは32バイトです。間違ったアラインメントはランタイムクラッシュを引き起こしますが、ベクトルはアロケータに関係なくコンパイルされません。 – watson1180

1

頻繁に使用されるresize()関数はすべての配置を引き起こしています。おそらく、あなたは__m128のベクトルテンプレートを特殊化することができますか?

関連する問題