2016-10-20 42 views
3

次のコードがセグメンテーションフォルトを引き起こすのはなぜですか?このようにしてユニオン内のポインタにアクセスすると、セグメンテーションフォルトが発生するのはなぜですか?

#include <string> 

union U { 
    bool boolean; 
    double number; 
    std::string* str_ptr; 
}; 

int main() 
{ 
    U u{new std::string("A")}; 
    delete u.str_ptr; 
    return 0; 
    // return u.str_ptr->compare("A"); 
} 

私は私が代わりにreturn文の他の方法でポインタにアクセスしようとした場合には関係していないようだと言う必要があります。例えば。 delete u.str_ptr; return 0;return u.str_ptr->compare("A");に置き換えます。まだセグメント化エラーが発生します。

がケースでは、これは私はそれが労働組合でthe last member setでない限りu.str_ptrにアクセスする法的ではありませんg++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609

答えて

5

を使用していますコンパイラ固有のものです。しかし、ユニオンで最後に設定されたメンバはbooleanです。これは、指定されていない値のイニシャライザリストが最初のメンバを設定するためです。

struct and union initializationの下にある "member lifetime"を参照してください。

+0

不適切な言語の参照を引用しています。幸いにも、書かれている時点(C++ではhttp://en.cppreference.com/w/cpp/language/union)で同じ(存在しないモジューロの指定された初期化子)も真です。 –

+0

あなたはリンクを変更しましたが、そのページには存在しない見積もりを... –

1

U u{new std::string("A")};あなたは何も特別なことを言っていないので、最初のメンバーをnewの呼び出しの値で初期化します。あなたが右のメンバーを設定したい場合は、次のようにします。

U u{.str_ptr=new std::string("A")}; 

--- EDIT ---

これはgcc拡張である、標準では、労働組合がブレースで囲まれた初期化子で初期化されると言う中括弧には、共用体の最初の非静的データメンバーのinitializer-clauseのみが含まれます。。次に、標準であなただけ行うことができます。

U u; 
u.str_ptr = new std::string("A"); 
+1

これはコンパイルされますか? C++の一部ではないC99指定の初期化子のようです。 – krzaq

+0

あなたは私の編集を見ることができます –

0

新によって返されたポインタは、暗黙のうちに最初のメンバー、すなわち、タイプboolの型に変換されています。 C++はこの変換を許可するのでエラーは発生しません。

// effectively what is happening. 
U u{ new std::string("A") != 0 }; 

このような組合を使用する場合は、明示的にメンバーに直接割り当てる方がよいでしょう。しかし、本当にこのようにしたい場合は、str_ptrを最初のメンバーにしてください。

関連する問題