2012-01-26 9 views
20

私は、悲惨な整数のオーバーフローが本当にいかにあるか疑問に思っていました。次のプログラム例テイク:32ビット・プラットフォーム上のa * aオーバーフローのでC++の整数オーバーフローはどれほど悲惨ですか?

#include <iostream> 

int main() 
{ 
    int a = 46341; 
    int b = a * a; 
    std::cout << "hello world\n"; 
} 

を、整数オーバーフローは未定義の動作をトリガし、私はすべてのことhello worldで任意の保証を持っています実際に私の画面上に表示されますか?


私は、次の標準的な引用符に基づいて、私の質問から一部を "署名" 削除:場合

(§5/ 5 C++ 03、§5/ 4 C++ 11)式の評価中に結果が数学的に定義されていないか、その型の表現可能な値の範囲にない場合、その動作は定義されていません。

(§3.9.1/ 4)unsignedと宣言された符号なし整数は、2^nを法とする算術の法則に従うものとします.nは整数の特定の値の値表現のビット数です。これは、の符号なし算術は、結果の符号なし整数型で表現できない結果が、結果の符号なし整数型で表現できる最大値よりも1だけ小さい値になるため、オーバーフローすることを意味しません()。

+1

C++でオーバーフローが発生したことはありません。数字は楽しくラップアラウンドし、プロセッサのオーバーフローフラグを設定します。 – Brain2000

+7

@ Brain2000ほとんどの場合、最適化の問題が発生します。 '(a + 1> a)'はオーバーフローにもかかわらず常に真です。 – Pubby

+0

[GCC Fail?または定義されていない動作?](http://stackoverflow.com/questions/7682477/gcc-fail-or-undefined-behavior) – Xeo

答えて

19

としては、(私は実際には最初のC++ chatでそれを育てた)コメントで@Xeoが指摘:
未定義の動作は、実際にそれを意味し、あなたは少なくともそれを期待するとき、それはあなたを打つことができます。

この最良の例はここにある:x86でWhy does integer overflow on x86 with GCC cause an infinite loop?

、符号付き整数オーバーフローが単純なラップアラウンドです。だから、普通は、と同じことがCやC++で起こると思います。しかし、コンパイラは介入することができます。を最適化する機会として、未定義の動作をで使用します。その質問から採取された例で

:GCCでコンパイルする場合

#include <iostream> 
using namespace std; 

int main(){ 
    int i = 0x10000000; 

    int c = 0; 
    do{ 
     c++; 
     i += i; 
     cout << i << endl; 
    }while (i > 0); 

    cout << c << endl; 
    return 0; 
} 

、GCCは、ループテストを最適化し、この無限ループとなります。

+2

この問題のもう1つの例がここにあります - > http://stackoverflow.com/questions/7124058/compiler-optimization-causing-program-to-run-slower – Joe

8

ハードウェアの安全機能を起動することがあります。だから、あなたは何の保証もありません。

編集: gccは-ftrapvオプションを持っています(ただし、私にとってはうまくいきません)。

+4

'-ftrapv'はシグナルのハンドラを登録した場合にだけ何もしません。クラッシュやその他の観察可能な動作はそれ自体では発生しません。 – sepp2k

+0

'-ftrapv'ではなく、' -fwrapv'拡張で符号なしオーバーフローのような符号付きオーバーフローを処理することを考えていますか? –

5

未定義の動作については2つのビューがあります。奇妙なハードウェアやその他の特殊なケースを集めるためにそこにあるという見解がありますが、通常はそれがうまく動作するはずです。そして何かが起こるという見解があります。そして、UB源に応じて、いくつかの意見があります。

オーバーフローに関するトラップまたは飽和のハードウェアと表現間の結果の違いを考慮に入れて、オーバーフローに関するUBが導入されている可能性があります。この場合、最初のビューについて議論することができます。本当に何かが保証されていない場合、実際に何かが起きる可能性があり、たとえ結果がそれ以上意味をなさない場合であっても、より速く動作するマシンコードを生成するために自由のすべての部分を使用しようとします。

したがって、未定義の動作が発生した場合は、何らかの問題が発生する可能性があると想定します。

+2

整数のオーバーフローについては未定義です。多くのプラットフォームでは、さもなければ不可能であろう。たとえば、整数xとyが負の値をとる唯一の方法がオーバーフローによるものであれば、コンパイラは符号なし演算(命令と関数呼び出しの違いを意味する)を使って 'x/y'を計算することができます。オーバーフローがUBになる符号なしタイプもありません。いくつかの最適化も可能になるからです。 – supercat

+0

しかし、このコメントを続けると、もっとも有用な最適化では、整数のオーバーフローが、奇妙な挙動をするナンセンス値を超えた結果をもたらすことはありません(例えば、同時に0より大きく、ゼロ)。 C標準には、UB以外のものを記述する方法はありませんが、計算に副作用がないという保証は、一般に非常に安価であり、非常に価値があります。それはもはや一貫してそれを提供していないコンパイラはあまりにも悪いです。 – supercat

関連する問題