未定義、未指定、および実装定義の動作

548
Zolomon 2010-03-08 11:10.

CおよびC ++の未定義の動作とは何ですか?不特定の動作と実装定義の動作はどうですか?それらの違いは何ですか?

8 answers

423
fredoverflow 2010-11-06 00:41.

未定義の振る舞いは、他の言語から来たプログラマーにとって驚くべきCおよびC ++言語の側面の1つです(他の言語はそれをよりよく隠そうとします)。基本的に、多くのC ++コンパイラがプログラムのエラーを報告しない場合でも、予測可能な方法で動作しないC ++プログラムを作成することは可能です。

古典的な例を見てみましょう:

#include <iostream>

int main()
{
    char* p = "hello!\n";   // yes I know, deprecated conversion
    p[0] = 'y';
    p[5] = 'w';
    std::cout << p;
}

変数pは文字列リテラルを指し、"hello!\n"以下の2つの割り当てはその文字列リテラルを変更しようとします。このプログラムは何をしますか?C ++標準のセクション2.14.5パラグラフ11によると、未定義の動作を呼び出します。

文字列リテラルを変更しようとした場合の影響は定義されていません。

「しかし、待ってください。これを問題なくコンパイルして出力を取得できますyellow」または「未定義の文字列リテラルは読み取り専用メモリに格納されているため、最初の割り当て試行でコアダンプが発生します」と叫ぶ人がいます。これはまさに未定義の振る舞いの問題です。基本的に、この標準では、未定義の振る舞い(鼻の悪魔でさえ)を呼び出すと、何でも起こります。言語のメンタルモデルによると「正しい」行動がある場合、そのモデルは単に間違っています。C ++標準には、唯一の投票期間があります。

未定義の動作の他の例には、境界を超えた配列へのアクセス、nullポインターの逆参照、存続期間が終了した後のオブジェクトへのアクセス、またはのような巧妙な式の記述が含まれi++ + ++iます。

C ++標準のセクション1.9では、未定義の振る舞いの危険性の低い2つの兄弟、未定義の振る舞い実装定義の振る舞いについても言及しています。

この国際規格のセマンティック記述は、パラメータ化された非決定論的抽象マシンを定義します。

抽象マシンの特定の側面と操作は、この国際規格で実装定義として説明されています(たとえばsizeof(int))。これらは、抽象マシンのパラメーターを構成します。各実装には、これらの点での特性と動作を説明するドキュメントを含める必要があります。

抽象マシンの他の特定の側面と操作は、この国際規格では指定されていないものとして説明されています(たとえば、関数への引数の評価の順序)。可能な場合、この国際規格は一連の許容可能な動作を定義します。これらは、抽象マシンの非決定論的側面を定義します。

他の特定の操作は、この国際規格では未定義として説明されています(たとえば、nullポインターの逆参照の影響)。[この国際規格は、未定義の動作を含むプログラムの動作に要件を課していません。エンドノート]

具体的には、セクション1.3.24には次のように記載されています。

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

未定義の動作に遭遇するのを避けるために何ができますか?基本的に、あなたは彼らが何について話しているかを知っている著者による良いC ++の本を読まなければなりません。インターネットチュートリアルをねじ込みます。ブルシルトをねじ込みます。

98
AnT 2010-03-08 11:15.

さて、これは基本的に標準からのストレートコピーペーストです

3.4.1 1実装定義の動作不特定の動作。各実装は、選択がどのように行われるかを文書化します。

2例実装定義の動作の例は、符号付き整数が右にシフトされたときの上位ビットの伝搬です。

3.4.3 1移植不可能または誤ったプログラム構成、または誤ったデータを使用した場合の未定義の動作動作。この国際規格は要件を課していません。

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

3例未定義の動作の例は、整数オーバーフローの動作です。

3.4.4 1不特定の動作不特定の値の使用、またはこの国際規格が2つ以上の可能性を提供し、どのような場合でも選択される要件を課さないその他の動作

2例不特定の動作の例は、関数への引数が評価される順序です。

60
AraK 2010-03-08 11:28.

おそらく、簡単な言い回しは、標準の厳密な定義よりも理解しやすいかもしれません。

実装定義の動作
この言語では、データ型があると言われています。コンパイラベンダーは、使用するサイズを指定し、実行した内容のドキュメントを提供します。

未定義の振る舞い
あなたは何か間違ったことをしています。たとえば、にint収まらない非常に大きな値がありcharます。その値をどのように入れますcharか?実際には方法はありません!何が起こる可能性もありますが、最も賢明なことは、そのintの最初のバイトを取得してchar。に入れることです。最初のバイトを割り当てるためにそれを行うのは間違っていますが、それは内部で起こることです。

不特定の動作
これら2つの機能のどちらが最初に実行されますか?

void fun(int n, int m);

int fun1()
{
  cout << "fun1";
  return 1;
}
int fun2()
{
  cout << "fun2";
  return 2;
}
...
fun(fun1(), fun2()); // which one is executed first?

言語は、左から右または右から左の評価を指定していません!したがって、不特定の動作が未定義の動作になる場合とそうでない場合がありますが、プログラムが不特定の動作を生成することはありません。


@eSKayあなたの質問はもっと明確にするために答えを編集する価値があると思います:)

fun(fun1(), fun2());動作は「実装が定義されている」のではないのですか?結局のところ、コンパイラはどちらかのコースを選択する必要がありますか?

実装定義と未指定の違いは、コンパイラーが最初のケースで動作を選択することになっているが、2番目のケースでは選択する必要がないことです。たとえば、実装には、の定義が1つだけ必要ですsizeof(int)。したがって、sizeof(int)プログラムの一部で4、他の部分で8であるとは言えません。コンパイラがOKと言うことができる不特定の動作とは異なり、これらの引数を左から右に評価し、次の関数の引数を右から左に評価します。同じプログラムで発生する可能性があるため、unspecifiedと呼ばれます。実際、指定されていない動作のいくつかが指定されていれば、C ++はより簡単になりました。そのためのStroustrup博士の答えをここで見てください:

コンパイラにこの自由を与えることと「通常の左から右への評価」を要求することとの間の違いは重要である可能性があると主張されています。私は確信が持てませんが、自由を利用する無数のコンパイラーとその自由を熱心に擁護する人々がいると、変更は難しく、CおよびC ++の世界の遠い隅に浸透するのに数十年かかる可能性があります。すべてのコンパイラが++ i + i ++などのコードに対して警告するわけではないことに失望しています。同様に、引数の評価の順序は指定されていません。

IMOの「もの」が多すぎて、未定義、未指定、実装定義などが残されています。ただし、これは簡単に言うことができ、例を示すこともできますが、修正するのは困難です。また、ほとんどの問題を回避して移植可能なコードを作成することはそれほど難しいことではないことにも注意してください。

27
Johannes Schaub - litb 2013-01-24 08:46.

公式のC根拠文書から

未指定の動作、未定義の動作、および実装定義の動作という用語は、標準で完全に記述されていない、または完全に記述できないプロパティを持つプログラムを作成した結果を分類するために使用されます。この分類を採用する目的は、標準への適合性のキャッシュを削除することなく、実装の品質を市場で積極的に発揮できるようにするだけでなく、特定の人気のある拡張機能を可能にする実装間の特定の多様性を可能にすることです。標準の付録Fは、これら3つのカテゴリのいずれかに分類される動作をカタログ化しています。

不特定の動作は、実装者にプログラムの翻訳にある程度の自由度を与えます。この許容範囲は、プログラムの翻訳に失敗するまでは拡張されません。

未定義の動作は、診断が難しい特定のプログラムエラーをキャッチしないように実装者にライセンスを与えます。また、準拠する可能性のある言語拡張の領域を識別します。実装者は、公式に定義されていない動作の定義を提供することにより、言語を拡張できます。

実装定義の動作により、実装者は適切なアプローチを自由に選択できますが、この選択についてユーザーに説明する必要があります。実装定義として指定された動作は、一般に、ユーザーが実装定義に基づいて意味のあるコーディング決定を行うことができる動作です。実装者は、実装定義をどの程度広範にするかを決定する際に、この基準を念頭に置く必要があります。不特定の動作と同様に、実装で定義された動作を含むソースの変換に失敗するだけでは、適切な対応にはなりません。

10
Anders Abel 2010-03-08 11:18.

未定義の振る舞いと不特定の振る舞いについては、簡単に説明しています。

彼らの最終的な要約:

要約すると、不特定の動作は、ソフトウェアがポータブルである必要がない限り、通常は心配する必要はありません。逆に、未定義の動作は常に望ましくなく、発生してはなりません。

8
supercat 2015-04-16 17:32.

歴史的に、実装定義の動作と未定義の動作はどちらも、標準の作成者が、品質の実装を作成する人々が判断を使用して、で実行されている目的のアプリケーションフィールドのプログラムに役立つ動作保証がある場合はそれを決定することを期待する状況を表しています。意図されたターゲット。ハイエンドの数値計算コードのニーズは、ローレベルのシステムコードのニーズとはまったく異なり、UBとIDBの両方により、コンパイラの作成者はこれらのさまざまなニーズに柔軟に対応できます。どちらのカテゴリーも、実装が特定の目的に、あるいはあらゆる目的にさえ役立つ方法で動作することを義務付けていません。ただし、特定の目的に適していると主張する品質の実装は、規格で要求されているかどうかに関係なく、そのような目的に適した方法で動作する必要があります。

実装定義の動作と未定義の動作の唯一の違いは、前者では、実装で何もできない場合でも、実装が一貫した動作を定義して文書化する必要があることです。それらの間の境界線は、実装が動作を定義するのに一般的に役立つかどうかではなく(コンパイラの作成者は、標準で要求されているかどうかに関係なく、実用的な場合に有用な動作を定義する必要があります)、動作の定義が同時にコストがかかる実装があるかどうかです。と役に立たない。そのような実装が存在する可能性があるという判断は、他のプラットフォームで定義された動作をサポートすることの有用性についての判断を意味するものではありません。

残念ながら、1990年代半ば以降、コンパイラの作成者は、動作の義務がないことを、動作の保証が不可欠なアプリケーション分野でも、実質的にコストがかからないシステムでも、コストに見合わないという判断として解釈し始めています。UBを合理的な判断を行使するための招待として扱う代わりに、コンパイラの作成者はUBをそうしない言い訳として扱い始めました。

たとえば、次のコードがあるとします。

int scaled_velocity(int v, unsigned char pow)
{
  if (v > 250)
    v = 250;
  if (v < -250)
    v = -250;
  return v << pow;
}

2の補数の実装では、正か負v << powvに関係なく、式を2の補数シフトとして扱うために労力を費やす必要はありません。

しかし、今日のコンパイラ作成者の間で好まれる哲学vは、プログラムが未定義の振る舞いを行う場合にのみ負になる可能性があるため、プログラムにの負の範囲をクリップさせる理由はないことを示唆していますv。負の値の左シフトは、重要なすべてのコンパイラでサポートされていましたが、既存のコードの多くはその動作に依存していますが、現代の哲学では、標準では左シフトの負の値はUBであると解釈されます。コンパイラの作成者はそれを無視してかまいません。

7
Suraj K Thomas 2015-03-17 21:11.

実装の定義-

実装者は、十分に文書化されている必要があり、標準は選択肢を提供しますが、必ずコンパイルすることを望んでいます

詳細不明-

実装定義と同じですが、文書化されていません

未定義-

何かが起こるかもしれません、それの世話をしてください。

6
4pie0 2014-05-11 02:35.

C ++標準n3337 § 1.3.10処理系定義の動作

実装に依存し、各実装が文書化する、整形式のプログラム構成と正しいデータの動作

C ++標準は、一部の構成に特定の動作を課さない場合がありますが、代わりに、特定の実装(ライブラリのバージョン)によって特定の明確に定義された動作を選択して記述する必要があると述べています。そのため、Standardで説明されていなくても、ユーザーはプログラムがどのように動作するかを正確に知ることができます。


C ++標準n3337 § 1.3.24未定義の動作

この国際規格が要件を課していない動作[注:この国際規格が動作の明示的な定義を省略している場合、またはプログラムが誤った構成または誤ったデータを使用している場合、未定義の動作が予想される場合があります。許容される未定義の動作は、予測できない結果で状況を完全に無視することから、環境に特徴的な文書化された方法で翻訳またはプログラムの実行中に動作すること(診断メッセージの発行の有無にかかわらず)、翻訳または実行の終了(発行あり)にまで及びます。診断メッセージの)。多くの誤ったプログラム構成は、未定義の動作を引き起こしません。それらは診断される必要があります。—エンドノート]

プログラムがC ++標準に従って定義されていない構成に遭遇すると、やりたいことを何でも実行できます(おそらく、私に電子メールを送信するか、あなたに電子メールを送信するか、コードを完全に無視します)。


C ++標準n3337 § 1.3.25 、不特定の行動

実装に依存する、整形式のプログラム構成と正しいデータの動作[注:実装は、発生する動作を文書化する必要はありません。可能な動作の範囲は、通常、この国際規格によって示されます。—エンドノート]

C ++標準は、一部の構造に特定の動作を課しませんが、代わりに、特定の実装(ライブラリのバージョン)によって特定の明確に定義された動作を選択する必要があると述べています(ボットは説明する必要はありません)。したがって、説明が提供されていない場合、ユーザーはプログラムがどのように動作するかを正確に知ることが難しい場合があります。

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

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

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

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

オーケーグッド770HPランボルギーニセンテナリオは十分に正気ではない

オーケーグッド770HPランボルギーニセンテナリオは十分に正気ではない

ランボルギーニの創設者であるフェルッチオランボルギーニが100歳になるのは毎日ではありません(そうです、彼は死んでいて、まだ死んでいると思います。

彼らが買った1台の車からAppleの車の計画について私たちが推測できること

彼らが買った1台の車からAppleの車の計画について私たちが推測できること

Appleが自動車分野に参入するという噂はかなり前から渦巻いており、AppleウォッチャーがSixtyEight Researchという会社がAppleの自動車研究開発のシェル会社である可能性が高いと判断したとき、その渦巻きは本当に渦巻いた。また、会社が購入した車は1台だけであることが知られており、その車はAppleが何を考えているかについての手がかりでいっぱいになる可能性があることも伝えています。

天文学者は太陽系の9番目の惑星の新しい証拠を見つけます

天文学者は太陽系の9番目の惑星の新しい証拠を見つけます

太陽系の外側にある架空の大きな物体である惑星Xの探索は、何十年にもわたって人間を魅了してきました。その検索の最新の章は、地球の10倍の大きさで、公転周期が15であるほど遠くにある惑星を指しています。

キャムニュートン、ゴッドダム

キャムニュートン、ゴッドダム

カムニュートンは昨日、簡単な265ヤードと3回のタッチダウンでファルコンズを引き裂き、別の素晴らしいゲームをしました。その日のハイライトは、上のタッチダウンスローでした。これは、視聴するたびにばかげているだけです。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language