2012-11-25 9 views
7

Dの整数オーバーフローを検出する方法は? (キャリーフラグをチェックする?)整数のオーバーフローを検出する

オリジナル例:

ubyte a = 100; 
ubyte b = 200; 
ubyte c = a + b; 
// c can't represent 300; how to detect the overflow now? 

改訂例:乗算とプリ/ポストインクリメントとも

uint a = 2_000_000_000; 
uint b = 3_000_000_000; 
uint c = a + b; 
// c can't represent 5_000_000_000; how to detect the overflow now? 

+2

は、C++で同じ質問をしています。http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-cc –

+1

およびアセンブリhttp://stackoverflow.com/質問/ 3925528/x86-アセンブリー-inc命令と-d命令命令とオーバーフローフラグ –

答えて

5

あなたは、いくつかのインラインアセンブリでかなり簡単に確認できます。

asm { jo overflowed; } // for checking signed types 
// or 
asm { jc overflowed; } // use this for checking unsigned types 

/* continue going */ 

return; 

overflowed: 

/* do whatever to handle it */ 

注:関数を呼び出すと、フラグをリセットすることができますので、あなたはおそらく機能でこれを置くことができません。関心のある操作の直後にインラインで配置したいと考えています。 http://arsdnet.net/dcode/ranged.dは、オーバーフローを起こすために演算子のオーバーロードを使用する型を作ることができます: http://arsdnet.net/dcode/ranged.dあるいは、モジュールは、標準的なライブラリのstd.bigintだと思います。これは、任意の大きな整数型を提供することによってオーバーフローを回避します。

+0

'jo' - * jump overflow *?これはまさに私が必要なもののように見えます。 –

+4

はい...しかし、実際には符号なしでオーバーフローが発生しないことに注意してください。-1:11111111のバイナリ表現を考えてみましょう(ここでは簡潔にするためにubyteを使用しています)。それは255と同じです。しかし、プロセッサは、型が署名されているかどうかを知りません。 255 + 1 == -1 + 1 == 0だから、キャリーフラグはセットされますが、オーバーフローフラグはセットされません。したがって、特に符号なしの数値を使用している場合は、代わりにjc命令(キャリーならジャンプ)が必要です。 –

+2

もう一つの潜在的な問題は、インクリメント命令がキャリーフラグをセットしていないことです。コンパイラはコンパイル時に+ 1をインクルードするように最適化します。だからあなたは+ bのために大丈夫ですが、それらはランタイムですから、+ 1または+ +はasmチェックに驚くようなパスを与えるかもしれません。 –

8

intより小さいすべての整数の計算がintで行われるため、最初に入力したコードはコンパイルされません。したがって、a + bの結果はintであり、intは暗黙的にubyteに変換されません。これはその変換が狭いためです。それをcに割り当てる場合は、それをキャストする必要があります。

ubyte c = cast(ubyte)(a + b); 

は今、それは明らかに未チェックの変換だし、(それが100200の値が与えられたキャストの結果なので)それが楽しくc44を詰め込むます。あなたがチェックし、変換したい場合は、std.conv.toを使用します。結果は要求された型に収まらないので、(ConvExceptionのサブクラスである)ConvOverflowExceptionをスローします

ubyte c = to!ubyte(a + b); 

キャストを自分で行い、オーバーフローがあったかどうかを確認するには、C/C++と本質的に同じボートにあり、キャリーフラグや並べ替えがありません。おそらく、あなたがアセンブリコードでチェックすると、そんなことがあるかもしれません。知りません。しかし、言語は確かにそのようなものを提供しません。 std.conv.toは、結果をチェックして、大きすぎるか小さすぎるかを調べることによって(引数の符号と型によって)調べます。

+0

オーバーフロービットも返す 'add'のような組み込み関数の追加はどうですか? – Mehrdad

+0

@Mehrdadオーバーフローに関連する余分な機能を提供する組み込み関数があるかもしれませんが、私はそれらについて何も知らない。それは私がこれまで扱っていたレベルよりも低いレベルであり、どのアーキテクチャでどれくらい多くのものがそこに存在することが保証されているか分かりません。 –

+0

サンプルコードは私の質問を説明するための模擬的なものです。あなたのレジャーで 'ubyte'を' uint'に置き換えてください。 –

関連する問題