C ++での最短の未定義動作サンプル[終了]


8

未定義の動作を示す、最も短くて整形式のC ++コードは何ですか?


1
「実行可能」とはどういう意味ですか?UBがある場合、実行できる保証はありません。
R.マルティーニョフェルナンデス

@ R.MartinhoFernandesよく、私はそれが始まることを意味します。
Luchian Grigore 2012

@LuchianGrigoreはコンパイラ(バージョン)に大きく依存しています。
rubenvb

1
「展示」を定義します。何かを示す必要がありますか?または、プログラム中のある時点で内部メモリの状態が未定義で十分ですか?
リスター氏2012

回答:


12
int main(){main;}

3.6.1メイン関数[basic.start.main]

3-[...]関数mainはプログラム内で使用しないでください。

編集:これは診断可能であるため、UBではありません。


int main(){for(;;);}

1.10マルチスレッド実行とデータ競合[intro.multithread]

24-実装は、任意のスレッドが最終的に次のいずれかを実行すると想定する場合があります。—終了、—ライブラリI / O関数の呼び出し、—揮発性オブジェクトへのアクセスまたは変更、または—同期操作またはアトミック操作の実行。


int main(){int i=i;}

4.1左辺値から右辺値への変換[conv.lval]

1-[...] glvalueが参照するオブジェクトが[...]初期化されていない場合、この変換を必要とするプログラムは未定義の動作をします。


//^L.

以下^Lは、基本的な文字セットの一部であるフォームフィード文字です。4文字(2.2:2ごとに改行は不要)。未定義の動作は

2.8コメント[lex.comment]

1-[a- //style]コメントにフォームフィードまたは垂直タブ文字がある場合、コメントとコメントを終了する改行の間には空白文字のみが表示されます。診断は必要ありません。


2つ目は未定義ではありません。問題なくforループを最適化できます。これは未定義の動作ではありません。
rubenvb

3
@rubenvb stackoverflow.com/questions/3592557/... - いつでも標準は、財産を持っているプログラムがない-Pは、未定義の意味を持っていることを暗示している「コンパイラは、Pをとることができる」と言います
ecatmur 2012

しかし、コンパイラは、コピーコンストラクタを省略しても副作用がないと想定する場合もあります。
rubenvb

@rubenvbは、その特定のケースが明示的に言及されているためです。
R.マルティーニョフェルナンデス

1
@BogdanAlexandru組み込みプロジェクトの動作が未定義です。つまり、今のところ期待どおりに機能する可能性がありますが、コンパイラをアップグレードすると動作が異なります。
ecatmur 2012年

5
\u\
0000

§2.2/ 1によると、これは8文字で、動作は未定義です。

バックスラッシュ文字(\)の直後に改行文字が続く各インスタンスは削除され、物理ソース行を結合して論理ソース行を形成します。物理的なソース行の最後のバックスラッシュのみが、そのようなスプライスの一部になる資格があります。その結果、universal-character-nameの構文と一致する文字シーケンスが生成された場合の動作は未定義です。


これは「プログラム」ではありません。プログラムにはがありmainます。
rubenvb

@rubenvb Hell ++で試してください。それは未定義の振る舞いを持っているので、なしのプログラムになることができますmain。従うべきルールのないプログラムを要求するときにルールを適用することは困難です(それがUBの意味です!)。
R.マルティーニョフェルナンデス

3
質問の文言に基づいて、私はこれが当てはまると思います-UBを表示する最も短い「コード」だけを要求します。しかし、コメントの「実行可能」に基づいて、その意図は、コードを除外する最も短いプログラムだったと思います。§3.6.1/ 1によると、これは、プログラムの指定された開始点です。」そのため、なしではmain、あなたが持っているものは不正な形式です。
ジェリーコフィン

1
@JerryCoffin彼はメインが必要ない自立した環境を使用しています。「メイン機能を定義するために自立環境のプログラムが必要かどうかは実装定義である」という3.6.1 / 1の残りの部分を都合よく省略しました。これは有効なプログラムです(引数に応じた「プログラム」なので、「有効」)。
David

ダン、ここに持って来ただけだ。+1
コロンボ2015

2
#include. /*Imagine a new-line right after the dot*/

§16.2/ 4:

次の形式の前処理ディレクティブ

             #include  pp-tokens改行

(前の2つの形式のいずれとも一致しない)は許可されます。[..]すべての置換の後に生成されるディレクティブが前の2つの形式のいずれとも一致しない場合、動作は未定義です。


ドットの前のスペースを削除しても同じように解析されませんか?
feersum

@feersumうん。これでアイデアが変わるわけではないので、読みやすさを高めるためにそれを避けたのですが、スペースを省略できることを説明するために問題のポイントを提供していると思います。ありがとう!
コロンボ2015年

2
int main(){int i=1>>-1;}

説明:

C ++ 98とC ++ 11§5.8/ 1はどちらも次のように述べています

右のオペランドが負の場合、または昇格した左のオペランドの長さ(ビット単位)以上の場合の動作は未定義です。


3
32ビットシステムで、ビット長はint通常32 ビットではありませんか?シフトのRHSの変更は-1同じ文字数であり、整数サイズに依存しません
ardnew

1

ウィキペディアを信じるなら、ここにいくつかあります:

文字列を変更すると、未定義の動作が発生すると言われています。それはいつも私のために働いています。

int main(int c,char*v){v[0]='.';}

戻り値のない非void関数は、未定義の戻り値を引き起こします。

int a(){}
int main(){return a();}

ゼロによる(int?の)除算はおそらく未定義です。私が知っているすべてはそれがクラッシュすることです。

int main(int c){c/0;}

これらは正当なコードスニペットではありません。メインはint main(){}最低でもとして定義する必要があります。
rubenvb

くそー、私は質問がCについてであると確信していました。
shiona

1
@shiona 2番目のパラメーターはにしchar **ないでくださいchar *。ポインタ値の一部を変更するだけです。実際、argv安全に変更できることが保証されています。
oldrinb 2012

標準では、文字列リテラルを読み取り専用にすることを許可しているため、多くの実装でこれが可能です。修飾子char *argv[]がないのは正しいことconstです。文字列リテラルに書き込むとクラッシュする可能性がありますint main(){char *v="";*v=1;}
Peter Cordes

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.