首页 文章

在Delphi中使用静态方式编辑动态数组

提问于
浏览
0

问:将动态数组转换为静态数组是否安全?

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 回答

  • 2

    我想你需要恢复你的逻辑 . 将静态数组转换为动态数组根本不安全(它在实际数据之前有一个计数器和引用计数),而相反的 - 将动态数组转换为静态数组指针 - 是完全安全的,如果你照顾缓冲区长度 .

    您的初始代码将触发一些随机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约定命名你的变量 . 也遵循相同的约定来区分代码中的静态数组和动态数组 .

  • 1

    这种方法当然不安全 . 静态数组与动态数组具有不同的内存布局 . 动态数组具有包含引用计数和长度的元数据 . 你可以在这个简短的摘录中侥幸成功,但这不是一种推荐的技巧 .

    无论问题是什么,这都不是解决方案 . 可能的解决方案可能涉及使用开放数组或指向字节的指针 .

相关问题