11

これらのコンパイラ チェック ディレクティブをオンにすると、範囲チェック エラーとオーバーフロー エラーの両方が発生するコードの要約バージョンを次に示します。これがオーバーフローを引き起こす理由を理解しています.C1の乗算で、データ型の最大値を超える可能性があるようです. しかし、なぜこれが Range-check エラーを引き起こすのでしょうか? スタック オーバーフローに関する Delphi のドキュメントやその他の投稿では、範囲チェック エラーは通常、範囲外の配列アクセスで発生するように思われます。しかし、範囲チェックエラーを引き起こしていると言っている行の配列にアクセスしていません。おそらくparam1への割り当てにあるのでしょうか?しかし、もしそうなら、なぜそれは範囲チェックであり、オーバーフローエラーではないのでしょうか?

const
  C1 = 44001;
  C2 = 17999;

function fxnName(..other params...; param1: Word): String;
var
  someByte: byte;
begin
  // some code
  // by now we're in a loop. the following line is where it breaks to in the debugger: 
  param1 := (someByte + param1) * C1 + C2;
  // more code
end;

関連する場合、デバッガーのその行で中断すると、Delphi に評価を依頼すると「宣言されていない識別子: 'param1'」と表示される param1 を除いて、すべての値が期待どおりに見えます。

4

1 に答える 1

20

範囲チェックに関するドキュメントには、次のように記載されています。

$R ディレクティブは、範囲チェック コードの生成を有効または無効にします。{$R+} 状態では、すべての配列および文字列インデックス式が定義された境界内にあることが検証され、スカラーおよびサブレンジ変数へのすべての代入が範囲内にあることがチェックされます。範囲チェックが失敗すると、ERangeError 例外が発生します (または、例外処理が有効になっていない場合はプログラムが終了します)。

したがって、ここでの理由は、上限範囲を超えた値が渡されるスカラー値への割り当てです。

単純型と部分範囲型の範囲チェック エラーについては、 docwiki 単純型も参照してください。

例:

{$R+} // Range check on
var
  w1,w2 : word;
begin
  w1 := High(word);
  w1 := w1 + 10; // causes range-check error on assignment to w1 (upper range passed)
  w2 := 0;
  w2 := w2 - 10; // causes range-check error on assignment to w2 (lower range passed)
end;

プラットフォームに依存しないすべての整数型に対する $R と $Q のすべての組み合わせの要約テスト:

            R+Q+  R+Q-  R-Q+
 ShortInt    R     R     x
 SmallInt    R     R     x
 Integer     O     x     O
 LongInt     O     x     O
 Int64       O     x     O
 Byte        R     R     x
 Word        R     R     x
 LongWord    O     x     O
 Cardinal    O     x     O
 UInt64      O     x     O

R=範囲エラー; O=オーバーフロー エラー。x=なし

そして、テストは32ビットモードのXE2で(疑似コード)でした:

number := High(TNumber);
number := number + 1;
于 2012-07-25T21:22:59.797 に答える