符号付きまたは符号なしのオーバフローの検出
説明
式の結果がその型の値の表現可能な範囲にあること、およびシフト量が有効であることをチェックします。
シフト演算のオーバフローはチェックされません。これは個別のチェックで処理されます。シフトする際のビット損失または未定義の動作の検出を参照してください。
チェックを実行する理由
符号付きオーバフローの動作は定義されておらず、符号なしのオーバフローの結果が望ましくない切捨てになることがあるためです。シフト演算はチェックされませんが、シフト量はチェックされます。これは、シフト量がマイナスまたは拡張された左オペランドの幅以上の場合に、シフト演算の動作が定義されないためです。
使用方法
コンパイラオプション: ‑‑runtime_checking signed_overflow|unsiged_overflow
IDE で、 [プロジェクト]>[オプション]>[ランタイム解析]>[整数オーバフロー]
1 つまたは複数のモジュールにチェックを適用できます。
チェックは、たとえばより大きな型で処理をするなどして、以下のように回避することができます。
int f(int a, int b)
{ return (int) ((long long) a + (long long) b); }
short g(short a, short b)
{ return (short) ( a + b); } /* Integer promotion occurs */
仕組み
コンパイラは、チェックが失敗することがないと判断しない限り、オーバフローする可能性のある各整数演算(+、-、*、/、%、単項の - を含む)、および各シフト演算でチェックを実行するコードを挿入します。
インクリメント / ディクリメント演算子(++/‑‑)および複合代入(+=、-= など)は、longhand (var = var op val)として記述されたときと同じようにチェックされます。
たとえば、++i と i += 1 はどちらも、i = i + 1 と記述されたかのようにチェックされます。この場合、オーバフローのチェックが有効化されていれば加算がチェックされ、変換のチェックが有効になっていれば代入がチェックされます。int と同じ、またはそれ以上のサイズを持つ整数型の場合、変換チェックが失敗することはありません。しかし、より小さい整数型の場合は、この種類の式におけるあらゆる失敗が一般的に変換エラーとなります。この例は以下のようになります。
signed char a = 127;
void f(void)
{
++a; /* Conversion check error (128 -> -128) */
a -= 1; /* Conversion check error (-129 -> 127) */
}コードサイズは大きくなります。アプリケーションにリソースの制約がある場合、オーバヘッドを最小限に抑えるため、このチェックはモジュール単位で使用してください。
例
C-RUNランタイムエラー解析を使用するにあたってに記載された手順に従ってください。[整数オーバフロー]オプションを使用します。
これは、実行時に識別されるソースコードの一例です。
C-RUN は符号付き整数オーバフロー、符号なし整数オーバフロー、またはシフトカウントオーバフローのいずれかを報告します。これは、リストされるメッセージの一例です。これは、リストされるメッセージの一例です。
