delphi - 在 Delphi 中对静态数组进行类型转换
问题描述
问:将动态数组转换为静态数组是否安全?
type
Bytearray = array of byte;
function calcCRC(buf1: pointer) : dword;
var
buf: ByteArray ;
outbuffer : array [1..30] of byte;
begin
buf := bytearray(buf1^); // <- is it safe ?
outbuffer[1] := buf[0];
end;
procedure test;
var
testarr : array [1..30] of byte ;
begin
calccrc(@testarr);
end ;
即使在使用 FastMM4 的相当大的程序中,这样的代码片段也能正确编译和工作。但有件事告诉我,这可能很危险......有什么建议吗?
解决方案
我想你需要恢复你的逻辑。将静态数组转换为动态数组根本不安全(它在实际数据之前有一个计数器和引用计数),而相反 - 将动态数组转换为静态数组指针 - 是完全安全的,如果你照顾缓冲区长度。
您的初始代码将触发一些随机 GPF(访问冲突),因为引用计数器将在某些隐藏代码中的 calcCRC() 中修改 - 使用 F2 查看 ASM:比您预期的要多,尤其是call DynArrayClear
其中很不安全。由于记忆中的内容,您还没有任何问题。但是,如果在数据之前存储了一个整数,例如 1,它将触发 GPF,因为离开 calcCRC() 会让 Delphi RTL 尝试释放动态数组实例。
如果您希望使用索引访问内存字节,则需要使用指向静态数组的指针,而不是动态数组。
代码可能如下:
Type
TByteDynArray = array of byte ;
TByteArray = array[0 .. (maxInt div sizeof(byte)) - 1] of byte;
PByteArray = ^TByteArray;
function calcCRCptr(buf1: PByteArray; buf1len: integer): dword;
var
outbuffer : array [1..30] of byte;
begin
result := 0;
// ensure you don't create any access violation by using big indexes
if buf1len < 1 then
exit; // avoid GPF
outbuffer[1] := buf1[0];
...
end;
function calcCRCdynarray(const buf1: TByteDynArray): dword;
begin
// you can use length(buf1) to get the number of items/bytes
result := calcCRCptr(pointer(buf1), length(buf1));
end;
procedure test ;
var
testdynarr: TByteDynArray;
teststaticarray: array[0..10] of byte;
begin
Setlength(testdynarr, 100);
calccrcdynarray(testdynarr) ; // safe
calccrcptr(pointer(testdynarr), length(testdynarr)); // direct call
calccrcptr(@teststaticarray, 11); // OK
end;
还要确保不要弄乱指针,例如,使用有关值 (T...) 和指针 (P...) 的正确 Delphi 约定命名变量。还要遵循相同的约定来区分代码中的静态数组和动态数组。
推荐阅读
- asp.net - 覆盖 Azure 应用设置中的 appsettings.json 值
- python - 旅行社类
- angular - 运算符 '>' 不能应用于类型 'string' 和 'number' 错误
- c# - 如何将 Roslyn 代码分析器添加到 Unity 项目?(适用于 2020 以下的 Unity 版本)
- flutter - 如何在浏览器中运行颤振单元测试?
- react-native - 未捕获的错误:java.net.ConnectException:无法连接到 /192.168.10.7:19000
- android - 是否可以通过另一个应用程序以编程方式控制一个应用程序的应用程序设置?
- python - 如何使 import 语句同时在 python 2 和 python 3 上工作
- visual-c++ - 在 c++ 项目中使用 spdlog
- python - Sklearn 训练测试拆分