Причина ошибки проверки диапазона (Delphi)

вот сокращенная версия некоторого кода, которая вызывает ошибку проверки диапазона и ошибку переполнения, если я включу эти директивы проверки компилятора. Я понимаю, почему это вызовет переполнение, при умножении C1 кажется вероятным, что оно может превысить максимальное значение типа данных. Но почему это также вызовет ошибку проверки диапазона? Документация 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;

Если это актуально, когда он ломается на этой строке в отладчике, все значения выглядят так, как ожидалось, кроме param1, который показывает "необъявленный идентификатор: 'param1'", когда я прошу Delphi оценить его.

1 ответов


документы о состояниях проверки диапазона:

директива $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=ошибка переполнения; х=ничего

и тест был (псевдо-код) с XE2 в 32-битном режиме:

number := High(TNumber);
number := number + 1;