在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字节内存而不考虑长度设置,那么SetLength
的重点是什么?
答案 0 :(得分:6)
要检测超出范围错误的数组索引,请设置范围检查错误。
$ R指令启用或禁用范围检查代码的生成。在{$ R +}状态中,所有数组和字符串索引表达式都被验证为在定义的范围内,并且所有对标量和子范围变量的赋值都被检查在范围内。如果范围检查失败,则引发ERangeError异常(或者如果未启用异常处理则终止程序。)
这是默认设置为{$ R-},但我建议将其设置为开启,至少在开发阶段。 它为代码增加了额外的开销,因此这可能是它默认关闭的原因。
如果您的设备经过良好测试并希望避免范围检查,请在设备顶部添加{$ R-}。这将在本地覆盖项目设置。
如果要避免代码块中的范围检查,可以使用此技术:
{$IFOPT R+}
{$DEFINE RestoreRangeCheck}
{$R-}
{$ENDIF}
{- Some code here }
{$IFDEF RestoreRangeCheck}
{$R+}
{$UNDEF RestoreRangeCheck}
{$ENDIF}