大家好:
   请先看这段代码!
///////////////////////////////////////
type
  class1=class
    field1:Integer;
  end;var
  obj1:class1;
begin
  obj1:=class1.create;
  obj1.field1:=11;
  obj1.desctory;
  //obj1.free;  //这里使用过,和上面的效果一样
  if obj1=nil then
  begin
    writeln('对象释放后为空指针!');
  end
  else
  begin
    writeln('对象释放后不是空指针!');
  end;
  obj1.field1:=12;
  writeln(obj1.field1);  //对象分别用free和destory释放,结果仍然可以访问!
  readln;
end.
///////////////////////////////////////
   大家应该明白我的问题了:为什么一个对象释放以后,仍然可以访问???   那么,应该如何真正释放掉一个对象呢?谢谢!

解决方案 »

  1.   

    建议你看一下《Delphi高手进阶》,讲的不错
      

  2.   

    首先,你free只是把对象所属的内存释放。但是对象的引用并没有清除(你需要使用c:=nil来清除)就是说obj1仍然指向其实例所在的内存块(虽然这个内存块已经不属于obj1了,但是里面的内容还没有清除)
    将你的代码做简单的修改:var
      obj1:class1;
      obj2:class1;
    begin
      obj1:=class1.create;
      obj1.field1:=11;
      obj1.Free;  if obj1=nil then
      begin
        showmessage('对象释放后为空指针!');
      end
      else
      begin
        showmessage('对象释放后不是空指针!');
      end;
      obj1.field1:=12;
      obj2:=class1.create;
      obj2.field1 := 99;
      showmessage(inttostr(obj1.field1));  //对象分别用free和destory释放,结果仍然可以访问!增加了一个obj2对象,并且在显示obj1.field1前创建了一个obj2的实例,将field1设置为99。可以看到obj1.field1变成99了,这就是:obj1占用的内存被释放并且被obj2使用了,但是obj1的引用还是指向原来自己占用的内存块,这就出现了obj1和obj2指向同一个内存块的情况。所以你在使用了一个对象后Free后还要将对象设置为nil。
      

  3.   

    object pascal的对象是在原有的Record的基础上改进而来的,如果你声明一个没有任何方法只有共有Field的类,那么他的行为方式很像record,比如不创建也可以访问field。
    但是,这只是实现中存在的一个副作用,并不包括在语言的定义中。在创建前或释放后访问对象的field都是对悬空地址的访问,只是由于现在的实现,使它恰好等于原有对象的地址,但这个空间是已经释放的,对这块空间的使用是非法的。
    另外object释放后,对象引用不会变为nil,只是变为悬空引用,需要自己将它赋为nil。
      

  4.   

    这个问题可以看这段代码(我把楼主的改了一下):
    var
      obj1,obj2:class1;
    begin
      obj1:=class1.create;
      obj1.field1:=11;
      ShowMessage(inttostr(obj1.field1));
      obj1.destroy;
      if obj1=nil then
      begin
        ShowMessage('对象释放后为空指针!');
      end
      else
      begin
        ShowMessage('对象释放后不是空指针!');
      end;
      obj2:=class1.Create;
      obj1.field1:=12;   ***********关键在这里1**********
      ShowMessage(inttostr(obj1.field1));
      ShowMessage(inttostr(obj2.field1));   ***********关键在这里2**********
      
      运行的结果,在2处,obj2.field1 居然是12 ?
      why ?
      因为,在 obj1,obj2:class1;处,声明对象的时候,只是为obj1和obj2分配了
      32bit的空间,此时,该空间的内容是无意义的,只有在obj1:=class1.create;之后,
      系统为obj1按照class1的定义,分配了相应的内存区域,并把obj1指向该空间。可以说,obj1的
      自己的32bit空间里存的是该内存区域的指针。
      当obj1.destroy之后,系统只是收回
      分配的内存区域(讲该区域设为空闲),此时,虽然obj1的值没变,但是,所指向的内存区域已经被系统回收了。
      正是因为这样,在obj2:=class1.Create;处,系统又从空闲空间中取出一段区域,分配给obj2。由于obj1的空间
      刚刚被释放,所以又把该段空间分配给了obj2,这就相当于obj1和obj2所指向的内存区域是同一块。所以,
      obj1.field1:=12; 也就改写了obj2.field1。本质上,obj1和obj2的内容(32bit的指针值)是相同的。
      
      
      楼主的问题的实质,只不过是系统回收了一段空间,但并未把指向该空间的指针置空。这样,就留下了可以通过该指针
      访问不该访问的空间的问题。
      
      一家之言,难免错误百出,恳请各位不吝赐教。