TListBox组件的那个AddObject函数,用于保存一个数字很方便,因为Object参数本来就是一个指针,说白了本来就是数字,所以AddObject('字符',TObject(12)),以后,需要取出数字直接Integer(Objects[...])即可,不必去释放所谓的Object对象,因为根本没对象创建。但是我要保存一个record记录就麻烦了,所以考录到了TObject对象,下面是一些方法:(1)、保存record的指针,发现record不做全局变量会丢失数据
type
   TRecord=record
     a,b:Integer;
   end;  
     var t:TRecord;
   begin
     t.a :=100;
     t.b :=100;
     ListBox1.Items.AddObject('测试',TObject(@t));//<--此处无法保存数据,因为变量t的指针是临时的。(2)、使用TObject对象
type
   TMyObject=class(TObject)
   public
      a,b:Integer;
   end;......
   var obj:TMyObject;
  begin
     obj :=TMyObject.Create;
     obj.a :=100;
     obj.b :=100;
     ListBox1.Items.AddObject('测试',obj);
  end;数据是保存了,但是突然纠结起来了,TMyObject对象需要释放吗?就好像TRecord记录是否需要释放一样模糊起来了,大家看Delphi的TObject的源代码,几乎没有一处做了任何实质性的工作,Create是空的,Destory是空的,那么TObject对象需要释放吗?

解决方案 »

  1.   

    TMyObj是要释放的
    你的方法1中,可以定义一个结构指针,然后New
    type
       PRecord=^TRecord;
       TRecord=record
         a,b:Integer;
       end;       var t:PRecord;
       begin
         new(t);
         t.a :=100;
         t.b :=100;
         ListBox1.Items.AddObject('测试',TObject(@t));
    不过,相应的,这个也要释放,需要dispose(xxxx);
      

  2.   

    TObject虽然似乎没东西,但据说编译器在里边搞了些花活,所以一个空的TObject也是需要释放的,你可以看一下TObject的InstanceSize值,这个差不多算是对象占用的空间吧
      

  3.   

    可以考虑让 TMyObject 继承自 TComponent,
    那么,当在 TForm1 下建立 TMyObject.Create(Self),
    最后它会自动释放。
      

  4.   

    Tobject的构造函数和析构函数为什么定义中为何没有代码,有两方面原因:1:
    详见《inside vcl 深入VCL架构剖析》第二章的2-6节,具体在79页2:
    详见《inside vcl 深入VCL架构剖析》中的第三章的3-2节,具体在“place holder方法”段。delphi的对象的实例都是在堆中申请内存创建的,堆中的对象的生命周期跟全局变量的生命周期一样,都是跟程序的生命周期一致的。只有在栈中申请的内存才会随清栈工作时自动回收。
    重申,create的对象一定要free,free的工作可以自己做也可以委托其他对象做,但必须明确自定确实做了free。
      

  5.   


    InstanceSize 是Class 函数,Class 函数是不需要创建对象即可使用,即:TObject.InstanceSize也是可以的,而且InstanceSize函数在TObject类里面没有哪个非class 函数使用它。突然感觉TObject对象很奇怪,它的代码太少了,几乎没什么可看,能看的有看不懂,全是汇编。大家记得CheatEngine源代码吗,就使用了这种方式,创建了TObject对象并AddObject,但是又不释放。如果能有内存泄露查看工具看一下,就知道不释放TObject对象是否会引起内存泄露。
      

  6.   

    因为TMyObject不止一次Create,当ListBox内容需要改变时,TMyObject就要Create,问题是,老的TMyObject需不需要释放,印象中记得对象创建都要Free,但是这个TObject倒让我糊涂了,当然,使用Free最安全,不Free是否也可以?
      

  7.   


    TmyCls = class(TComponent)
        private
        fName: string;
        procedure setName(s:string);
        published
        property Name:string read fName write setName;
      end;procedure TmyCls.setName(s: string);
    begin
              if s<>'' then
              fName:=s;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Tobj: TmyCls;
    begin
      Tobj := TmyCls.Create(Self);
      Tobj.Name := 'Hello world';
      ShowMessage(Tobj.Name);
      {Tobj.Free;}//不用释放由Owner回收,不建议这样,最终由Owner关闭时回收
    end;
      

  8.   


    这个应该是,对象创建时即默认全局对象,即使它在一个函数内临时创建,但是被AddObject使用它后会继续延续,这和Record记录完全不一样,Record记录不申请为全局变量,它只在函数内有效,函数外被释放,事实证明也是这样。
      

  9.   


    InstanceSize 是Class 函数,Class 函数是不需要创建对象即可使用,即:TObject.InstanceSize也是可以的,而且InstanceSize函数在TObject类里面没有哪个非class 函数使用它。突然感觉TObject对象很奇怪,它的代码太少了,几乎没什么可看,能看的有看不懂,全是汇编。大家记得CheatEngine源代码吗,就使用了这种方式,创建了TObject对象并AddObject,但是又不释放。如果能有内存泄露查看工具看一下,就知道不释放TObject对象是否会引起内存泄露。
    肯定是泄露了,有什么好怀疑的。说到检测内存的工具,EurekaLog 是第一神器,可以搜搜看看它如何用。
    还有一个就是fastmm。如果你用的是delphi2007及以上版本,可以简单地program Project1;uses
      Forms,
      Unit1 in 'Unit1.pas' {Form1};{$R *.res}begin
      Application.Initialize;
      ReportMemoryLeaksOnShutdown:=True; // 加入该行,在程序运行并关闭后会提示你什么对象在哪里泄露了
      Application.MainFormOnTaskbar := True;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.
      

  10.   

    record 非TOBJECT,跟integer、single这些同属值类型。
    而且似乎你有点混淆
    var
     pInt: ^integer
      int: integer;
    begin
      int:= 100; // int 是值类型的100
      getmem(pInt,4); // pInt 是指针,在堆中分配了4字节内存
      freemem(pInt); // pInt需要手动释放,而int不需要,它在栈中创建,函数结束就自动清栈一并销毁
    end;
     
      

  11.   

    是的,TObject需要Free,我也觉得要Free,下面是CheatEngine 561 的代码,多处使用AddObject,但是有Free函数调用type Tpathspecifier=class(TObject)
      public
        path: string;
    end;
    ........
    var
        fullpath: Tpathspecifier;
    ............
    fullpath:=Tpathspecifier.Create;
    fullpath.path:=opendialog1.filename;
    clbPlugins.Items.AddObject(extractfilename(opendialog1.FileName)+':'+pluginname,fullpath);
    ..........
    Tpathspecifier(clbPlugins.Items.Objects[clbplugins.ItemIndex]).Free;另外请教9楼兄弟,我用Delphi7,没用Delphi2010,主要是2010对String申明相关改变,导致我的老工程很多String都要重新申明。Delphi7用什么内存泄露工具检测?
      

  12.   

    另外,6楼兄弟说的我还是搞不懂,TComponent用Create(Self)会自动释放?应该不会吧,又不是.net,内存泄露就是不断增加内存,而且不用的内存又不释放,典型的就是对象创建后不释放,相当于不停的增加全局变量,虽然这些对象大部分在主程序结束后会被释放,但是只要主程序在运行,终究会因为内存占用过多导致系统崩溃,这就是内存泄露。
      

  13.   

    TListBox 是 TComponent
    你可以用 TMyComponent.Create(ListBox)来确保它随ListBox释放
      

  14.   

    由Owner来维护生命周期已经不是什么了不起的东西,
    最新版Delphi,
    TStringList.Create时可以传入一个参数,
    使StringList负责Object的释放。所以,利用TComponent的机制释放TMyObject,
    无所谓好或不好,
    只看能否解决问题。
      

  15.   

    12楼的兄弟,你方法不行的,因为ListBox在整个主程序周期都不会释放,因为那是个可视控件,怎么可能销毁,而ListBox在不停的更新保存Tobject,所以无效的TObject只能销毁释放。