无论问谁,都会说分配的资源一定要释放,但是我遇到以下两个问题希望有高人能够帮忙解惑:
1。使用GetMem(P,1024000000)分配了将近一个G的内存。按理说在至少在程序结束时要释放调,否则会发生内存泄漏。但是我故意没有释放,打开任务管理器观察,当程序结束的时候,内存使用量会恢复到程序运行以前,也就是说没有发生内存泄漏,为什么?2。在使用xxx.Create(AOwner)(注:AOwner<>nil,以下都如此),VCL会帮助程序员释放资源。当使用xxx.Create(nil)时,需要自己释放。我作了个测试,如下:首先定义了一个类:
TMyClass = class
private
  ListBox: TListBox;
  P: Pointer;
public
  constructor Create(AOwner: TComponent);
  destructor Destroy; override;
end;implementation{ tmy }constructor tmy.create(AOwner: TComponent);
begin
  ListBox := TListBox.Create(AOwner); //AOwner在我的测试中是TForm1
  GetMem(P, 1024000000);
end;destructor tmy.Destroy;
begin
  ListBox.Free;
  FreeMem(P);
  inherited;
end;我创建了这个类的实例,指定了AOwner是TForm1,代码如下:
  ...
   procedure TForm1.Button1Click(Sender: TObject);
   begin
     myclass := TMyClass.Create(Self); //myclass是一个全局变量
   end;问题:
  (1)当我没有自动释放时,经过跟踪发现,系统确实释放了ListBox,但是不是经过我所写的Destroy函数,而是直接调用的TListBox类的Destroy函数。除非我在窗体OnClose事件中手动加入代码调用MyClass.Free程序才会执行我的TMyClass.Destroy,否则根本不会执行它。 这样的话给指针P分配的内存就没有机会释放了。
难道说想要保险的话,不论调用Create函数时是否指定拥有者,都要调用一下Free函数吗?
  (2)这个问题就雷同于第一个大问题了:既然系统没有给我释放指针对象P所分配的内存,我有没有手动释放,那么应该会有内存泄漏问题。但是查看任务管理器的结果,依然是内存正常释放了。如何解释。难道Delphi也和java一样有垃圾回收机制?

解决方案 »

  1.   

    1.TForm1做主窗体和普通窗体时,运行结果是不一样的。
    主窗体退出就是程序结束,一般会对所申请的资源全部做释放。
    如果是普通窗体释放,在它里面分配的资源不会释放,也就是P分配的内存就没有机会释放释放了ListBox不是你写的Destroy释放,是因为你创建时用的参数AOwner(ListBox := TListBox.Create(AOwner); ); //AOwner在我的测试中是TForm1 
    是窗体TForm1 释放时,捎带着把Owner指向它的一起释放了2.这个是软件退出内存后,释放的。不在对象资源管理的范畴中。
      

  2.   

    谢谢madyak 的回答,不过还有一点不明白的问题:
    按madyak 的说法,如果我动态创建了一个对象,用的创建参数AOwner不是主窗体(同时也不是nil),那么即便指定了拥有者,我同样需要自己调用free方法来释放,这样才有机会释放我的P分配的内存。那么如果我上边的对象是作为一个可视化控件放置到了非主窗体上(比如说Form2),那么来回创建释放几次Form2,程序就会死翘翘咯。可实时上我们在使用控件的时候即便放置到了非主窗体上,我们也没有手动去释放这些控件,程序也并不会因为非主窗体创建释放多次就会死掉,这又怎么解释?
      

  3.   

    TMyClass = class 
    private 
      ListBox: TListBox; 
      P: Pointer; 
    public 
      constructor Create(AOwner: TComponent); 
      destructor Destroy; override; 
    end;
    你注意到你声明的类了没有?是直接继承TObject,它没有Owner的。 你在Create时,虽然有Owner参数,但它自身没有Owner从属机制。
    如果你把TMyClass = class (TComponent ),则执行情况,又会和你上面说的不一样。一个组件,不管是可视还是不可视的,都是TComponent
    后代,所以Owner都会有联带关系,会自动执行子的Destroy。TMyClass = class 这样的类,没有Owner,自然不会执行子的Destroy。还有你的代码也有点问题。
    constructor tmy.create(AOwner: TComponent); 
    begin 
      ListBox := TListBox.Create(AOwner); //AOwner在我的测试中是TForm1 ,一般不给传AOwner,要么传Self,要么传nil。直接传AOwner,会导致得释放两次,有地址错误。拥有者释放时会把ListBox 释放一次,而tmy释放时,又会释放一次。
      GetMem(P, 1024000000); 
    end; 
      

  4.   

    首先:所有的程序都是在一个虚拟内存空间运行的,由系统来进行总的管理。当程序关闭后,这个程序内所分配的内存是系统自动全部释放的。象 TListBox 这样的控件,如果你指定了Owner, Owner在释放时会将所有以自己为OWNER的控件释放掉。如果控件是你在开发期放在窗体上的,你不用管它的释放问题。对于你自己在程序中动态创建的对象,一般都是要自己手动释放的。
      

  5.   

    如何发分啊,好像跟原来不一样了。再麻烦下madyak,怎么给你加分阿?