我在DLL中返回一个动态数组,比如
procedure fun(var arr: tarr of Tmyrec);数组长度是在函数中通过setlength来设定的我的问题是,这个数组的生命周期是到什么时候??我发这个问题是担心函数返回后,这段内存会被delphi回收导致exe中接受的数据错误
exe可能是任何语言,不仅限于delphi
那么通过这种方式返回数据,是否安全?

解决方案 »

  1.   

    不安全,delphi和其他语言动态数组机制不同,可能会导致结果错误,你可以试试指针数组,虽然比较麻烦,但却是全windows通用的
      

  2.   

    嗯,这个知道。但我想知道的是 是不是函数返回了,delphi就认为该指针可以回收了?
    如果是的话,那也就是说exe中从这个函数所获取的指针已经是不安全的了?
      

  3.   

    这个数组变量是传出类型的,应该不由dll来控制生命周期吧。
      

  4.   

    我的理解是,这段数组内存空间是在DLL里申请的(SetLength),EXE应该并不知道这个空间的大小吧?
    EXE应该不太可能会管理这段内存。如果是DLL来管理,那DLL也不知道EXE中会使用这个数组到什么时候难道说是在进程结束时回收?那这样内存会被一直占用,如果重复执行函数的话。
      

  5.   

    Caller中第1种情况
    procedure xxx;
    var
      arr: tarr of Tmyrec;
    begin
      DLLFun(arr);  //DLL申请数组的内存,xxx只提供一个指针地址给,DLLFun中填一个地址到arr上
    end;//这里会释放本过程中的自动管理内存的变量,如String,Array,Variant等
    释放一个在DLL中申请的内存,在都没有引用ShareMem.pas的情况下,要异常/溢出.Caller中第2种情况
    var
      arr: tarr of Tmyrec;//全局变量
    procedure xxx;
    begin
      DLLFun(arr);  //DLL申请数组的内存,xxx只提供一个指针地址,DLLFun中填一个地址到arr上
    end;//这里不会执行任何关于arr的操作
    这种情况下,arr变量的内存会一直存在,直到进程结束.如果始终保证同一个DLL执行SetLength,而且只在这个DLL中SetLength(多次执行/不同的函数中执行都一样)就不会导致内存泄露,而且arr也能正常使用
    但是:如果中途释放了DLL(FreeLibrary),那这个arr指针指向的内存将变得不确定(随着DLL释放而释放),如果Exe和DLL或者其他DLL都有对这个array的SetLength,是不正确的,异常.
    如果都引用了ShareMem.pas除外.正确的作法:
    Exe中申请内存,DLL填值,并返回填了多少个值
    procedure xxx;
    var
      arr: tarr of Tmyrec;
      Count : integer;
    begin
      SetLength(arr, MaxCount);
      Count := DLLFun(arr);//由于array同时具有长度,所以这里不需要传MaxCount进去了
      for i:=0 to Count-1 do ...
    end;
      

  6.   

    这种还是EXE中申请空间,DLL只是读写这个空间的为好,一般程序应该遵循谁申请谁释放这样比较好
      

  7.   

    动态数组是自动管理的,不用特意的去释放,提前释放设置为nil就行了,即arr:=nil;
      

  8.   


    kiboisme大哥真给力啊,每次都分析的很好,帮助我解决了不少疑难问题呀
    其实我发现windows api都是用这种方式传值的,exe申请缓冲区,dll填入数据
    只是这种方式要提前知道缓冲区的size,大多数时候不得不把缓冲区设大些