我在程序中定义了这样一个动态数组:procedure DoSomething;
var
  …
  aDynamicArray: array of TAClass;
begin
  …
  setlength(aDynamicArray, Length);
  …
  for i:=1 to Length do
  begin
    aDynamicArray[i].Free;
    aDynamicArray[i] := nil;
  end;
end;结果老是出错,后来把
  for i:=1 to Length do
  begin
    aDynamicArray[i].Free;
    aDynamicArray[i] := nil;
  end;
部分删掉就正常了,哪位知道为什么,解释一下。不显式地调用free不会造成内存泄漏吗?

解决方案 »

  1.   

    楼主应该说明一下错误的提示信息。
    "Length"不知道楼主要代表什么,它本身是Delphi的一个函数名称,如果“Length”是代表一个Integer类型的变量的话,我估计错误是数组越界了。setlength(aDynamicArray, Length);//数组定义的范围在0~Length-1
    ...
     for i:=1 to Length do//这里越界了
    ...
    //应该改为
    setlength(aDynamicArray, iLength);
    ...
    for i:=0 to iLength do
    ...
      

  2.   

    不好意思!写错了!//应该改为
    setlength(aDynamicArray, iLength);
    ...
    for i := 0 to iLength - 1 do
    ...
      

  3.   

    同意liyinwei(月夜彩虹)的,或者在free了之后,后面是否还用到了?
      

  4.   

    同意liyinwei(月夜彩虹)的,
    另外关于"
    不显式地调用free不会造成内存泄漏吗?"
    动态数组属于自管理类型,系统会自动释放,就象string类型一样,一般情况下不需要手动释放的,即使要释放,也不是free,而是
    1、将数组变量赋值为nil;
    2、调用函数:finalize
      

  5.   

    for i:=low(aDynamicArray) to high(aDynamicArray) do
      begin
        if Assigned(aDynamicArray) then 
        begin 
           try
            aDynamicArray[i].Free;
            aDynamicArray[i] := nil;
           except     end;
      end;
    end;
      

  6.   

    不好意思,问题中打错了,我很清楚动态数组是从0开始的。再把问题写清楚些:procedure DoSomething;var
      …
      aDynamicArray: array of TAClass;
    begin
      …
      setlength(aDynamicArray, Len+1);
      …
      for i:=1 to Len do
        aDynamicArray[i]:=TAClass.Create;
      …
      for i:=1 to Len do
      begin
        aDynamicArray[i].Free;
        aDynamicArray[i] := nil;
      end;
    end;又试了几次,调用free是没问题的。但如果去掉最后那个循环,会不会有内存泄漏的问题?
      

  7.   

    如果aDynamicArray[0]没有被Create过的话,就不会有内存泄漏的问题。
      

  8.   

    liyinwei(月夜彩虹):我自己试了一下,下面这段程序是会耗尽内存的unit dynamicArray;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;  TAClass = class
        c: char;
        destructor Destroy;override;
      end;procedure test;var
      Form1: TForm1;implementation{$R *.dfm}procedure test;
    var
      i, n: integer;
      aDynamicArray: array of TAClass;
    begin
      n := 1000000;
      setlength(aDynamicArray, n);
      for i:=1 to n-1 do
      begin
        aDynamicArray[i] := TAClass.Create;
        aDynamicArray[i].c := 'a';
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      i:integer=0;
    begin
      for i:=1 to 10000 do 
        test;
    end;{ TAClass }destructor TAClass.Destroy;
    begin
    //证明内存没有被释放
      form1.Edit1.Text := 'free';
      inherited;
    end;end.  
      

  9.   

    小鱼:
    你的程序逻辑上并没有问题。
    但你按下“Button1”的时候,程序Create 了10000000000个TAClass!!!
    你知道这些TAClass要占用多少内存吗?你算一下吧,一个TACLass占用4个字节,它们加起来要占用9.5G的内存!!!!!!!!!!!
    我不知道你的内存有多少,但是你的内存有1G的话,你还要添置9G内存才能运行你的程序!!
    问题不是它没有释放内存,而是你的内存不够用(估计你没有10G的内存),还没到运行到释放内存的代码的地方,你的程序已经停止了,系统估计也要停止相应了。
    我已经测试过,只要你Create TACLass的数量不超过你内存所能负担的话,完全可以被释放的。
      

  10.   

    还有,只要是手动Create的类都需要释放的,不然就会内存泄漏的问题。
    这其中有2种情况
    1.Create的时候指定了类的所有者,如:
    var
      sl: TStringList;
      lb: TLabel;
    begin
      sl := TStringList.Create;  //没有指定sl的所有者
      lb := TLabel.Create(nil);  //同样没有指定lb的所有者
    ...
      sl.Free;//需要手动释放
      lb.Free;//需要手动释放
    end;2.Create的时候指定了所有者,可以不手动释放
    var
      lb: TLabel;
    begin
      lb := TLabel.Create(self);//指定了lb的所有者为self
      //这种情况不手动释放都不会造成内存泄漏,它的释放由它指定的所有者self负责
      //但是为了不浪费系统资源,建议还是用完lb后手动释放 lb.Free;
    ...
    end;
      

  11.   

    改一下:1.Create的时候没有指定类的所有者,如:
      

  12.   

    liyinwei(月夜彩虹):
    问题不是它没有释放内存,而是你的内存不够用(估计你没有10G的内存),还没到运行到释放内存的代码的地方

    Create的时候指定了类的所有者
    …真是你越说我越糊涂啊。
    从test过程退出时都不释放内存,什么时候才"运行到释放内存的代码"?我结束程序的时候吗?
    什么叫Create的时候指定了类的所有者?你知道Create(AOwner)这个方法是哪来的吗?一个普通的类能指定所谓的类的所有者吗?
      

  13.   

    1.在你贴出来的代码部分没有释放内存的代码,这是我看漏眼了,因为你的问题的重点不在于此;
    2.“Create的时候指定了类的所有者”,对于这句要你自己去体会,很难作更详细的说明;
    3.有的类创建的时候可以指定所有者,有些不能指定所有者,这是类固有的;
    4.如果是你自己写的类,就看你的类怎么写,指定还是不指定所有者完全有你决定。
      

  14.   

    我看问题是
     for i:=Length To 0 Dowen do   <-----------------------
      begin
        aDynamicArray[i].Free;
        aDynamicArray[i] := nil;
      end;
    end;
      

  15.   

    liyinwei(月夜彩虹):
    你先看一下tobject的声明,再看看tcomponent的声明,然后再来讨论好吗?