2012-04-03 33 views
5

私は、ユーザー定義データ(すなわち、プラグインから)を格納するための構造を持っています。そのデータを格納するための所定の最大サイズを持つchar[]があります。型打ち、char []と参照解除

struct A 
{ 
    // other members omitted 
    // data meant to be type punned, only contains PODs 
    char data[256]; 
}; 

次に、Aからキャストする静的関数を持つサンプルのユーザー構造があります。

g++ -O3 -std=c++0x -Wall -o test test.cpp(GCC 4.6.1)でコンパイルします。

これは、dereferencing type-punned pointer will break strict-aliasing rules警告をトリガします。 char*と同じルールに従うと思った記憶装置としてchar[]を使用して以来、私はそれが大丈夫だろうと思っていました。私はそれが奇妙なことがわかりません。そうでしょう ?名前:まあ、...私は今変更することはできませんので、移動しましょう。私はGCCが出力任意の警告をしません、ここでは何もデリファレンスおりませんので

struct B 
{ 
    .... 
    static B* FromA_ptr(A& a) 
    { 
     // static_assert that sizeof(B) < sizeof(A::data) 
     return reinterpret_cast<B*>(a.data); 
    } 
} 

今度は、次のような方法を考えてみましょう。私が後でBへのポインタを使用しても、それはどちらもしません。

A a; 
auto b = B::FromA_ptr(a); 
b->i = 2; // no warnings. 

これは安全ですか?問題を解決するよりもむしろ自分の道を歩いているように感じます。私のために->はまだ何とか変数を逆参照しています。

また、効果を達成するための方法はありますか? I.別の構造体の中のストレージからキャストされた変更可能な参照(またはポインタ)を取得しますか? Aが定義されていて、プラグインを介して追加されたものがある場合、格納されているタイプのセットが不明であるため、連合は機能しません。memcpyは唯一安全な方法だと思われますがはるか)

+0

私は専門家ではありませんが、あなたは '__may_alias__'属性を探していますか? http://blog.worldofcoding.com/2010/02/solving-gcc-44-strict-aliasing-problems.html –

+0

とにかく、どのようにアライメントの問題に対処していますか? – curiousguy

+0

@curiousguy:これまでのところ私はしないでください。 x86では、私は最悪の場合でもパフォーマンスを低下させるかもしれないと思います。私は何も自動ベクトル化しようとしていないので、 '__attribute __(aligned(8)));'で十分でしょう。おそらく 'may_alias'はGCCにあまりにも多くの奇妙なことをする前に整列に注意を払うように指示しています。 –

答えて

3

答えはノー、それは安全ではありませんです(このSO questionを参照)

GCCは、ポインタがエイリアスできないことを前提としています。たとえば、あるものを他のものから割り当てて、他のものから読み込んだ場合、GCCは最適化として、読み書きを並べ替えることができます - 私はこれが生産コードで起こるのを見ましたが、デバッグするのは楽しいことではありません。使用されるタイプの

属性((may_alias))は、おそらくあなたは、コードの特定のセクションのための仮定を無効に得ることができる最も近いです。