[解決済み] 非アクティブな組合員へのアクセスと未定義の動作?
質問
へのアクセスは
union
メンバにアクセスすることは UB であるという印象を持っていましたが、確かな参考文献を見つけることができないようです (UB であると主張する回答以外では、標準からのサポートはありません)。
つまり、未定義の動作なのでしょうか?
どのように解決するのですか?
この混乱は、C 言語では明示的に共用体を介した型抜きを許可しているのに対し、C++( c++11 ) にはそのような許可がないことです。
6.5.2.3 構造と組合員
95) 組合オブジェクトの内容を読み取るために使用されるメンバが、オブジェクトに値を格納するために最後に使用されたメンバと同じでない場合、その値のオブジェクト表現の適切な部分は再解釈されます。 オブジェクトに値を格納するために最後に使用されたメンバと同じではない場合、値のオブジェクト表現の適切な部分は、新しい型のオブジェクト表現として再解釈されます。 を、6.2.6 で述べたように新しい型のオブジェクト表現として再解釈する(このプロセスは''型パニング''と呼ばれることもある)。 punning''と呼ばれることもある)。これはトラップ表現になるかもしれません。
C++の状況です。
9.5 ユニオン[class.union]について
ユニオンでは、非静的データメンバのうち最大1つはいつでもアクティブであることができます。 すなわち、非静的データメンバのうち最大1つの値は、いつでもユニオンに格納することができます。
C++では、後に、以下のものを含むユニオンの使用を許可する言語があります。
struct
を含むユニオンの使用を許可する言語があります。
ユニオンのタイプパニングが可能かどうかを判断するために は が C++ で許可されているかどうかを判断するには、さらに調査する必要があります。 思い出してみてください。 c99 は C++11 の規範となる参照文献です(そして C99 には、和集合の型抜きを許可する C11 と同様の言語があります)。
3.9 型 [基本.型]
4 - 型Tのオブジェクトのオブジェクト表現は、型Tのオブジェクトが占有するN個のunsigned charオブジェクトのシーケンスである。 ここで、Nはsizeof(T)に等しい。オブジェクトの値表現は、型Tの値を保持するビットのセットです。 オブジェクトの値表現は,型Tの値を保持するビットの集合です。コピー可能な型の場合、値表現はオブジェクト表現に含まれるビットの集合です。 これは実装で定義された値の集合の1つの離散的な要素である。 値を決定するオブジェクト表現のビットの集合です。 42
42) C++のメモリモデルは、ISO/IEC 9899 Programming Language Cのメモリモデルと互換性があることを意図しています。
を読むと、特に興味深いものになります。
<ブロッククオート3.8 オブジェクトの寿命 [基本的な.life]について
タイプTのオブジェクトの寿命は、以下の時に始まります。 - 型Tの適切なアライメントとサイズを持つストレージが取得されたとき。 - オブジェクトが自明でない初期化を持っている場合、その初期化が完了したとき。
つまり、プリミティブ型(これは は は些細な初期化を持っている) に対して、オブジェクトの寿命は少なくともユニオン自体の寿命を包含しています。 これによって
3.9.2 複合型 [basic.compound]について
T型のオブジェクトがアドレスAにある場合、アドレスAを値とするcv T*型のポインタは、値がどのように得られたかにかかわらず、そのオブジェクトを指すと言われます。 のポインタは、その値がどのように得られたかに関係なく、そのオブジェクトを指すと言われます。
私たちが興味を持っている操作が型抜き、つまり非アクティブなユニオン メンバーの値を取ることであると仮定し、そのメンバーによって参照されるオブジェクトへの有効な参照を持っていることを上記のように考えると、その操作は lvalue から rvalue への変換となります。
4.1 L値からR値への変換 [conv.lval]
非関数、非配列型のglvalue
T
はprvalueに変換することができます。 もしT
が不完全な型である場合、この変換を必要とするプログラムは不正な形式となります。 もしglvalueが参照するオブジェクトが型T
から派生した型のオブジェクトでなくT
から派生した型でない場合、あるいはオブジェクトが初期化されていない場合、 この変換を必要とするプログラムは未定義の振る舞いをします。
そこで問題は、非アクティブなユニオンメンバーであるオブジェクトは、アクティブなユニオンメンバーへのストレージによって初期化されるのかどうかです。 私が知る限りでは、これはそうではないので、もしもの話ですが。
-
にコピーされます。
char
配列ストレージにコピーして戻す (3.9:2)、または - が同じ型の別の論理和にバイト単位でコピーされる (3.9:3)、あるいは
- ISO/IEC 9899に準拠したプログラム要素によって言語境界を越えてアクセスされた場合 (それが定義されている限り) (3.9:4注42)。
非アクティブメンバによる組合へのアクセスは が定義されている であり、オブジェクトと値の表現に従うように定義されているため、上記のいずれかの介在がないアクセスは未定義な動作となる。 これは、実装ではもちろん未定義の動作が発生しないと仮定することができるため、このようなプログラムで実行が許可される最適化に対して影響があります。
つまり、非アクティブなユニオンメンバーに対して合法的にlvalueを形成することができますが(なぜ構築なしで非アクティブなメンバーへの代入がOKなのか)、それは初期化されていないとみなされます。
関連
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] 未定義の動作とシーケンスポイント
-
[解決済み] 未定義、未指定、および実装で定義された動作
-
[解決済み】なぜこれらのコンストラクトはプリインクリメントとポストインクリメントを使用して未定義の動作をしているのでしょうか?
-
[解決済み】CとC++におけるユニオンの目的
-
[解決済み】f(i = -1, i = -1)の挙動が未定義なのはなぜ?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み】CとC++におけるユニオンの目的