客户在运行旧版Delphi 7应用程序的工厂中嵌入的计算机上报告Range check error
。我们还没有能够重现错误。他们给我们发了一张照片:
软件可以连续几天正常运行,我们目前只有关于如何 生成或可靠复制的模糊线索。我的理解是这个错误发生在两个一般场景中:
(1) An array or string has been accessed outside its bounds
(2) The variable is assigned a value out-of-range for its type
如果只有40个元素,则(1)的一个例子是访问数组[50]。 (2)的示例是将值“300”分配给无符号BYTE。
这来自SO question 1和SO question 2。我有很多仔细的检查来尝试识别有问题的线路!
我的问题是这个错误是如何产生的。上述两个问题都涉及{$R+}
编译器指令。在项目选项>编译器>运行时错误Range checking
已关闭,代码中没有任何地方使用{$R+}
(也不是{$R-}
)。这个错误是怎么发生的?应用程序不应该崩溃或生成不同的异常吗?
答案 0 :(得分:4)
我将回答这个问题:
是否可以在未明确启用的情况下生成范围检查错误?
但是,您在客户的网站上遇到的问题需要进一步调查才能解决。通常这种事情需要结合:
是的,未经特别启用,生成范围检查错误 。
raise ERangeError.Create(...);
引发范围检查错误。如果被调用,无论范围检查设置的状态如何,都会引发错误。注意代码可以如果这样写,也遵守以下设置:
{$IFOPT R+}
raise ERangeError.Create(...);
{$ENDIF}
但重点是,只要调用raise <SomeClass>.Create(...)
,就会引发 异常 。如果您搜索Delphi源代码,您将找到引发ERangeError
的几个地方。 Loki的回答提供了一个例子。
{$R}
设置不是全局的。如果您使用此设置编译项目,请关闭,但在已打开选项的情况下编译的DCU中的链接:那么对于那些DCU仍然 。< / LI>
醇>
此外,可以针对特定代码段本地更改设置。 E.g。
{$IFOPT R-} {$R+} {$DEFINE TOGGLE_ROFF} {$ENDIF}
{ Ensure range-checking is on, but turn off again if it was already off.}
procedure MustUseRangeChecking(...);
begin
...
end;
{$IFDEF TOGGLE_ROFF} {$R-} {$ENDIF}
注意:您可以在自己的代码中使用{$IFOPT}
来检查范围检查指令的状态。
答案 1 :(得分:3)
是的,可以在没有专门启用范围检查错误的情况下提升
例如只看TStream.SetSize函数:
procedure TStream.SetSize(const NewSize: Int64);
begin
if (NewSize < Low(Integer)) or (NewSize > High(Integer)) then
raise ERangeError.CreateRes(@SRangeError);
SetSize(LongInt(NewSize));
end;
所以它会在启用或不启用范围检查错误的情况下引发异常。你在delphi中有这样的几个函数。