未定義の動作とシーケンスポイント

1000

「シーケンスポイント」とは何ですか?

未定義の振る舞いとシーケンスポイントの関係は何ですか?

a[++i] = i;気分を良くするために、のような面白くて複雑な表現をよく使います。なぜそれらの使用をやめるべきですか?

これを読んだ場合は、フォローアップの質問「未定義の振る舞いとリロードされシーケンスポイント」に必ずアクセスしてください。

(注:これは、StackOverflowのC ++ FAQへのエントリを意味します。このフォームでFAQを提供するというアイデアを批評したい場合は、これをすべて開始したメタへの投稿がそのための場所になります。その質問は、FAQのアイデアが最初に始まったC ++チャットルームで監視されているため、アイデアを思いついた人があなたの答えを読む可能性が非常に高くなります。)

5 answers

688
Prasoon Saurav 2010-11-14 19:39.

C ++ 98およびC ++ 03

この答えは、C ++標準の古いバージョンに対するものです。標準のC ++ 11およびC ++ 14バージョンには、正式には「シーケンスポイント」が含まれていません。代わりに、操作は「前にシーケンスされます」または「シーケンスされていない」または「不確定にシーケンスされます」。正味の効果は基本的に同じですが、用語が異なります。


免責事項:わかりました。この答えは少し長いです。それで、それを読んでいる間、忍耐を持ってください。あなたがすでにこれらのことを知っているならば、それらをもう一度読むことはあなたを夢中にさせることはありません。

前提条件:C ++標準の基本的な知識


シーケンスポイントとは何ですか?

標準は言う

シーケンスポイントと呼ばれる実行シーケンス内の特定の指定されたポイントで、前の評価のすべての副作用が完了し、後続の評価の副作用が発生していないものとします。(§1.9/ 7)

副作用?副作用とは何ですか?

式の評価は何かを生み出し、さらに実行環境の状態に変化があった場合、その式(その評価)には何らかの副作用があると言われています。

例えば:

int x = y++; //where y is also an int

初期化操作に加えて、演算子のy副作用によりの値が変更され++ます。

ここまでは順調ですね。シーケンスポイントに移ります。comp.lang.cの作者によって与えられたseq-pointsの交互の定義Steve Summit

シーケンスポイントは、ほこりが落ち着き、これまでに見られたすべての副作用が完了することが保証されている時点です。


C ++標準にリストされている一般的なシーケンスポイントは何ですか?

それらは:

  • 完全な式の評価の最後に(§1.9/16)(完全な式は、別の式の部分式ではない式です。)1

    例:

    int a = 5; // ; is a sequence point here
    
  • 最初の式の評価後の次の各式の評価(§1.9/182

    • a && b (§5.14)
    • a || b (§5.15)
    • a ? b : c (§5.16)
    • a , b (§5.18)(ここで、a、bはコンマ演算子です。inはコンマ演算子でfunc(a,a++) ,はなく、引数aとの間の単なる区切り文字a++です。したがって、その場合の動作は定義されていません(aプリミティブ型と見なされる場合))
  • 関数呼び出し時(関数がインラインであるかどうかに関係なく)、関数本体の式またはステートメントの実行前に行われるすべての関数引数(存在する場合)の評価後(§1.9/17)。

1:注:完全式の評価には、字句的に完全式の一部ではない部分式の評価を含めることができます。たとえば、デフォルトの引数式(8.3.6)の評価に関係する部分式は、デフォルトの引数を定義する式ではなく、関数を呼び出す式で作成されたと見なされます。

2:示されている演算子は、5項で説明されているように、組み込み演算子です。これらの演算子の1つが有効なコンテキストでオーバーロードされ(13節)、ユーザー定義の演算子関数を指定すると、式は関数呼び出しを指定し、オペランドは、それらの間に暗黙のシーケンスポイントがなくても、引数リストを形成します。


未定義の振る舞いとは何ですか?

標準セクションに未定義の動作を規定する§1.3.12ように

この国際規格が要件を課していない、誤ったプログラム構成または誤ったデータの使用時に発生する可能性があるような動作3

この国際規格が行動の明示的な定義の説明を省略している場合にも、未定義の行動が予想される可能性があります。

3:許容される未定義の動作は、予測できない結果で状況を完全に無視することから、環境に特徴的な文書化された方法で翻訳またはプログラムの実行中に動作すること(診断メッセージの発行の有無にかかわらず)、翻訳または実行の終了にまで及びます。 (診断メッセージの発行を伴う)。

要するに、未定義の振る舞いは、デーモンがあなたの鼻から飛び出し、あなたのガールフレンドが妊娠するまで、何でも起こり得ることを意味します。


未定義の振る舞いとシーケンスポイントの関係は何ですか?

その前に、未定義の振る舞い、未指定の振る舞い、および実装定義の振る舞いの違いを知っておく必要があります。

また、それを知っている必要がありthe order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecifiedます。

例えば:

int x = 5, y = 6;

int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.

ここに別の例があります。


今の標準は§5/4言う

  • 1)前のシーケンスポイントと次のシーケンスポイントの間で、スカラーオブジェクトは、式の評価によって、格納されている値を最大で1回変更する必要があります。

どういう意味ですか?

非公式には、2つのシーケンスポイント間で変数を複数回変更してはならないことを意味します。式ステートメントでは、next sequence pointは通常、終了セミコロンにあり、previous sequence pointは前のステートメントの終わりにあります。式に中間を含めることもできますsequence points

上記の文から、次の式は未定義の振る舞いを呼び出します。

i++ * ++i;   // UB, i is modified more than once btw two SPs
i = ++i;     // UB, same as above
++i = 2;     // UB, same as above
i = ++i + 1; // UB, same as above
++++++i;     // UB, parsed as (++(++(++i)))

i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)

ただし、次の式は問題ありません。

i = (i, ++i, 1) + 1; // well defined (AFAIK)
i = (++i, i++, i);   // well defined 
int j = i;
j = (++i, i++, j*i); // well defined

  • 2)さらに、前の値は、格納される値を決定するためにのみアクセスされるものとします。

どういう意味ですか?つまり、オブジェクトが完全な式内に書き込まれる場合、同じ式内のオブジェクトへのすべてのアクセスは、書き込まれる値の計算に直接関与する必要があります

たとえばi = i + 1i(LHSおよびRHSでの)すべてのアクセスは、書き込まれる値の計算直接関与します。だから大丈夫です。

このルールは、法的な表現を、アクセスが明らかに変更に先行する表現に効果的に制限します。

例1:

std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2

例2:

a[i] = i++ // or a[++i] = i or a[i++] = ++i etc

のアクセスのi1つ(の1つa[i])は、最終的にiに格納される値(で発生する)とは関係がないため、許可されi++ません。したがって、定義するための適切な方法はありません。コンパイラー-増分値が格納される前または後にアクセスを実行する必要があるかどうか。したがって、動作は定義されていません。

例3:

int x = i + i++ ;// Similar to above

ここでC ++ 11の回答をフォローアップします。

277
Prasoon Saurav 2010-11-16 01:12.

これは私の以前の回答のフォローアップであり、C ++ 11関連の資料が含まれています。


前提条件:関係(数学)の初歩的な知識。


C ++ 11にシーケンスポイントがないというのは本当ですか?

はい!これは非常に真実です。

C ++ 11では、シーケンスポイントSequenceedBeforeSequenceedAfter(およびUnsequencedIndeterminately Sequenced)の関係に置き換えられました。


この「前にシーケンスされた」ことは正確には何ですか?

前にシーケンス(§1.9/ 13)は次のような関係です。

  • 非対称
  • 推移的

単一のスレッドによって実行され、厳密な半順序を誘発する評価の間1

正式には、任意の2つの評価を与えられた意味(下記参照) AB、場合Aれる前に配列決定され B、その後の実行はA 先行するものの実行をB。もしA前に配列決定されていないBB前に配列決定されていないA場合、A及びBあるunsequenced 2

評価AとはBされている不定、配列決定のいずれかのときAの前に配列決定されBたりBする前に、配列決定されるAが、それは指定されていない3

[注]
1:厳密半順序である二項関係 "<"セット上Pでありasymmetric、そしてtransitive全てのために、すなわち、ab、及びcP:、我々は持っている
........(I)。a <bの場合¬(b <a)(asymmetry);
........(ii)。a <bおよびb <cの場合、a <c(transitivity)。
2:順序付けられていない評価の実行は重複する可能性があります。
3:不確定に順序付けられた評価重複できません、どちらかを最初に実行できます。


C ++ 11のコンテキストでの「評価」という言葉の意味は何ですか?

C ++ 11では、式(または部分式)の評価には一般に次のものが含まれます。

  • 値の計算(glvalue評価のためにオブジェクトのIDを決定し、prvalue評価のためにオブジェクトに以前に割り当てられた値をフェッチすることを含む)および

  • 副作用の開始。

今(§1.9/ 14)は言う:

完全な式に関連付けられたすべての値の計算と副作用は、評価される次の完全な式に関連付けられたすべての値の計算と副作用のシーケンスされます。

  • 簡単な例:

    int x; x = 10; ++x;

    に関連++xする値の計算と副作用は、の値の計算と副作用の後にシーケンスされます。x = 10;


ですから、未定義の振る舞いと上記のものとの間には何らかの関係があるはずですよね?

はい!正しい。

(§1.9/ 15)では、

特に明記されていない限り、個々の演算子のオペランドおよび個々の式の部分式の評価は順序付けられていません4

例えば ​​:

int main()
{
     int num = 19 ;
     num = (num << 3) + (num >> 3);
} 
  1. 演算子のオペランドの評価は、+相互に関連して順序付けられていません。
  2. <<>>演算子のオペランドの評価は、相互に関連して順序付けられていません。

4:プログラムの実行中に複数回評価される式で、unsequenced及び不定配列決定し、その部分式の評価が異なる評価で一貫して行う必要はありません。

(§1.9/ 15)演算子のオペランドの値の計算は、演算子の結果の値の計算の前にシーケンスされます。

意味するx + yの値の計算xとはyの価値計算の前に配列決定されます(x + y)

さらに重要なことには

(§1.9/ 15)スカラーオブジェクトへの副作用がどちらかに対して順序付けられていない場合

(a)同じスカラーオブジェクトに対する別の副作用

または

(b)同じスカラーオブジェクトの値を使用した値の計算。

動作は未定義です。

例:

int i = 5, v[10] = { };
void  f(int,  int);
  1. i = i++ * ++i; // Undefined Behaviour
  2. i = ++i + i++; // Undefined Behaviour
  3. i = ++i + ++i; // Undefined Behaviour
  4. i = v[i++]; // Undefined Behaviour
  5. i = v[++i]: // Well-defined Behavior
  6. i = i++ + 1; // Undefined Behaviour
  7. i = ++i + 1; // Well-defined Behaviour
  8. ++++i; // Well-defined Behaviour
  9. f(i = -1, i = -1); // Undefined Behaviour (see below)

関数を呼び出すとき(関数がインラインであるかどうかに関係なく)、任意の引数式、または呼び出された関数を指定する後置式に関連付けられたすべての値の計算と副作用は、本体のすべての式またはステートメントの実行前にシーケンスされます。関数と呼ばれます。[注: 異なる引数式に関連する値の計算と副作用は順序付けられていません。—エンドノート]

(5)(7)および(8)未定義の動作を呼び出さないでください。詳細な説明については、次の回答を確認してください。

  • C ++ 0xの変数に対する複数のプリインクリメント操作
  • シーケンスされていない値の計算

最後の注意

投稿に欠陥を見つけた場合は、コメントを残してください。パワーユーザー(担当者> 20000)は、タイプミスやその他の間違いを修正するために、投稿を編集することを躊躇しないでください。

31
AlexD 2017-09-12 22:50.

C ++ 17N4659)には、式の評価のより厳密な順序を定義する、慣用的なC ++の式の評価順序の改良の提案が含まれています。

特に、次の文

8.18代入および複合代入演算子
...。

いずれの場合も、代入は、右オペランドと左オペランドの値計算の後、代入式の値計算の前に順序付けられます。右のオペランドは、左のオペランドの前にシーケンスされます。

次の説明と一緒に

Xに関連するすべての値の計算とすべての副作用が、式Yに関連するすべての値の計算とすべての副作用の前にシーケンスされる場合、式Xは式Yの前にシーケンスされると言われます。

問題のケースを含め、以前に定義されていない動作のいくつかのケースを有効にします。

a[++i] = i;

ただし、他のいくつかの同様のケースでは、未定義の動作が発生します。

N4140

i = i++ + 1; // the behavior is undefined

しかし、 N4659

i = i++ + 1; // the value of i is incremented
i = i++ + i; // the behavior is undefined

もちろん、C ++ 17準拠のコンパイラを使用することは、必ずしもそのような式を書き始める必要があることを意味するわけではありません。

11
Yttrill 2010-12-08 09:44.

変更には根本的な理由があると思います。古い解釈を明確にするのは単なる見た目だけではありません。その理由は並行性です。精緻化の不特定の順序は、いくつかの可能なシリアル順序の1つを選択するだけです。これは、指定された順序がない場合、同時評価が可能であるため、順序の前後とはまったく異なります。古いルールではそうではありません。例:

f (a,b)

以前はa、b、またはb、aのいずれかでした。これで、aとbは、インターリーブされた命令または異なるコアでさえも評価できます。

2
awiebe 2018-10-26 17:40.

ではC99(ISO/IEC 9899:TC3)、これまでこの議論から欠席思われる以下のsteteentsはevaluaitonの順序について作られています。

[...]部分式の評価の順序と副作用が発生する順序はどちらも指定されていません。(セクション6.5 pp 67)

オペランドの評価の順序は指定されていません。代入演算子の結果を変更しようとしたり、次のシーケンスポイントの後でそれにアクセスしようとした場合、動作は定義されていません。(セクション6.5.16 pp 91)

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

アトランタのドナ・ブラジル:「私があなたに私の話をするとき私を踏まないでください」

アトランタのドナ・ブラジル:「私があなたに私の話をするとき私を踏まないでください」

2017年11月19日にアトランタで開催されたドナブラジルとモーアイボリー(ダグスミスフォトグラフィー)ドナブラジルを見逃すことはありません。

彼らは北朝鮮から脱出した亡命者の胃の中に奇妙な寄生虫を見つけました

彼らは北朝鮮から脱出した亡命者の胃の中に奇妙な寄生虫を見つけました

画像:ゲッティ陰謀愛好家は新しくてエキサイティングなディスカッション資料を持っています:国境を越えて韓国に5発撃たれた北朝鮮の脱北者は寄生虫でいっぱいで、そのうちの1人は南のメディアは、寄生虫を持った北朝鮮の脱北者を見つけることは珍しいことではないと報告している、実際、男性が30以上のタイプを持っていたケースがあった。

パニッシャーの第2話は、複雑な陰謀の網を織り交ぜています

パニッシャーの第2話は、複雑な陰謀の網を織り交ぜています

写真:パニッシャー(Netflix)これらのMarvel Netflixが愛していることが1つあるとすれば、それは複雑な政府や企業の陰謀です。そして、なぜこれらのショーがそのルートを選択するのかを理解するのは簡単です。

最新のBoseヘッドフォンは音楽を聴くためのものではなく、パートナーの鼻を鳴らすためのものです。

最新のBoseヘッドフォンは音楽を聴くためのものではなく、パートナーの鼻を鳴らすためのものです。

あなたのパートナーはチェーンソーのように詮索し、あなたを眠らせませんか?あなたのパートナーはあなたがチェーンソーのように詮索したと主張しますが、あなたが詮索しないので彼らは彼の想像ですか?あなたのケースが何であれ、Bose(はい、ハイエンドオーディオ機器のメーカー)はあなたのために何かを持っています。それらはBoseSleepbudsと呼ばれます。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

ムーアの法則を超えて

ムーアの法則を超えて

計算に対する私たちの欲求とムーアの法則が提供できるものとの間には、指数関数的に増大するギャップがあります。私たちの文明は計算に基づいています—建築と想像力の現在の限界を超える技術を見つけなければなりません。

Language