问:将动态数组转换为静态数组是否安全?
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的大型程序中,这样的代码段也能正常编译和工作 . 但有些东西告诉我,它可能很危险......有什么建议吗?
2 回答
我想你需要恢复你的逻辑 . 将静态数组转换为动态数组根本不安全(它在实际数据之前有一个计数器和引用计数),而相反的 - 将动态数组转换为静态数组指针 - 是完全安全的,如果你照顾缓冲区长度 .
您的初始代码将触发一些随机GPF(访问冲突),因为在某些隐藏代码中将在calcCRC()中修改引用计数器 - 使用F2查看ASM:有超出您的预期,尤其是
call DynArrayClear
这是非常不安全的 . 由于你记忆中的内容,你还没有任何问题 . 但是,例如,在数据之前存储1个整数,它会触发GPF,因为离开calcCRC()会让Delphi RTL尝试释放动态数组实例 .如果您希望使用索引访问内存字节,则需要使用指向静态数组的指针,而不是动态数组 .
代码可能如下:
还要确保不要乱用指针,例如:你用适当的关于值(T ...)和指针(P ....)的Delphi约定命名你的变量 . 也遵循相同的约定来区分代码中的静态数组和动态数组 .
这种方法当然不安全 . 静态数组与动态数组具有不同的内存布局 . 动态数组具有包含引用计数和长度的元数据 . 你可以在这个简短的摘录中侥幸成功,但这不是一种推荐的技巧 .
无论问题是什么,这都不是解决方案 . 可能的解决方案可能涉及使用开放数组或指向字节的指针 .