Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 为什么访问动态数组的越界索引不';你不能提高AV吗?_Delphi_Delphi Xe2 - Fatal编程技术网

Delphi 为什么访问动态数组的越界索引不';你不能提高AV吗?

Delphi 为什么访问动态数组的越界索引不';你不能提高AV吗?,delphi,delphi-xe2,Delphi,Delphi Xe2,在VCL中,TByteDynArray被定义为动态数组: type TByteDynArray = array of Byte; 但似乎没有进行索引边界检查: var DataBytes: System.Types.TByteDynArray; i: Integer; begin SetLength(DataBytes, 2); DataBytes[5] := 222; // Accessing index beyond set length. i := DataBytes

在VCL中,
TByteDynArray
被定义为动态数组:

type TByteDynArray = array of Byte;
但似乎没有进行索引边界检查:

var
  DataBytes: System.Types.TByteDynArray;
  i: Integer;
begin
  SetLength(DataBytes, 2);
  DataBytes[5] := 222; // Accessing index beyond set length.
  i := DataBytes[5]; // `i` is now set to "222".
上面的代码运行时没有错误


为什么不像静态数组那样引发
AccessViolation
?如果可以访问和修改数组变量的65536字节内存,而不考虑设置的长度,那么设置长度有什么意义?

要检测数组索引越界错误,请启用范围检查错误

$R指令启用或禁用范围检查代码的生成。在{$R+}状态下,验证所有数组和字符串索引表达式是否在定义的范围内,并检查标量和子范围变量的所有赋值是否在范围内。如果范围检查失败,将引发ERangeError异常(如果未启用异常处理,则程序将终止)

这是默认设置为{$R-},但我建议至少在开发阶段设置它。 它会给代码增加额外的开销,因此这可能是它默认关闭的原因


如果您有一个经过良好测试的单元,并且希望避免范围检查,请在单元顶部添加{$R-}。这将在本地覆盖项目设置

如果要避免代码块中的范围检查,可以使用以下技术:

{$IFOPT R+}
  {$DEFINE RestoreRangeCheck}
  {$R-}
{$ENDIF}

{- Some code here }

{$IFDEF RestoreRangeCheck}
  {$R+}
  {$UNDEF RestoreRangeCheck}
{$ENDIF}

默认情况下禁用范围检查;使用
$r+
启用它上面的代码运行时不会出错。大概也许不是。是否存在错误是不可预测的。您永远无法预测被覆盖的内容。有时这是一场灾难,有时它会带来一些微妙的错误。你只是运气不好,没有出现错误。另一次,你会写一些重要的东西,并在其他地方使用。你使用了很多不正确的假设作为基础,你的问题在结果上没有多大意义。静态数组可能不会导致A/V假定超出绑定的内存分配给其他对象。如果在最后一页边界下紧密分配,动态数组可能会导致A/V。然而,我确信,使用默认的FastMM对齐方式,访问2字节数组边界以上3字节的内容永远不会崩溃。因此,您的答案是-您正在以填充字节的形式存储值222。感谢您提供了有用的答案。您能给我一些指导,我是否应该打开它(而不是在代码中进行显式范围检查)?为什么默认情况下不启用此选项?@NewWorld您应该始终在启用范围检查和溢出检查的情况下运行(至少在调试配置中)。将其作为IDE的默认设置。我不明白为什么默认情况下不打开。一个愚蠢的设计决策,因为人们通常将数组定义为整数的
A=array[0..0],然后动态地为它分配(一大块)内存。看了很多VCL。在这种情况下,您不需要
{$R+}
。不过,默认情况下它应该是开着的。@Johan,这并不能解释任何事情。VCL代码可以很容易地使用$R,甚至更好地避免这种构造。如果Emba在意,他们将默认启用范围和溢出检查。有些VCL代码很差,这很难成为让新手没有安全网的理由。@Johan,通常当你有意放弃控制时,你要确保代码块周围有范围检查。