当前位置:  开发笔记 > 程序员 > 正文

为什么即使在调用后也分配了Delphi对象.Free?

如何解决《为什么即使在调用后也分配了Delphi对象.Free?》经验,为你挑选了2个好方法。

在Delphi中,为什么在调用析构函数后Assigned()函数仍然返回True?

下面的示例代码将向控制台写入"sl仍然已分配".

但是,我可以打电话给FreeAndNil(sl); 它不会被分配.

我已经在Delphi中编程了一段时间,但这对我来说没有意义.

谁能解释一下?

program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, Classes;

var
  sl : TStringList;

begin
  sl := TStringList.Create;
  sl.Free;
  if Assigned(sl) then
    WriteLn('sl is still assigned')
  else
    WriteLn('sl is not assigned');
end.

我尝试比较VCL操作... FreeAndNil简短而且很有意义:

procedure FreeAndNil(var Obj);
var
  P: TObject;
begin
  P := TObject(Obj);
  TObject(Obj) := nil;  // clear the reference before destroying the object
  P.Free;
end;

但TObject.Free是神秘的汇编程序,我不明白:

procedure TObject.Free;
asm
        TEST    EAX,EAX
        JE      @@exit
        MOV     ECX,[EAX]
        MOV     DL,1
        CALL    dword ptr [ECX].vmtDestroy
@@exit:
end;

Toon Krijthe.. 37

如果使用sl.Free,则释放对象但变量sl仍指向现在无效的内存.

使用FreeAndNil(sl)释放对象并清除指针.

顺便说一下,如果你这样做:

var
  sl1, sl2: TStringList;
begin
  sl1 := TStringList.Create;
  sl2 := sl1;
  FreeAndNil(sl1);
  // sl2 is still assigned and must be cleared separately (not with FreeAndNil because it points to the already freed object.)
end;




procedure TObject.Free;
asm
    TEST    EAX,EAX
    JE      @@exit              // Jump to exit if pointer is nil.
    MOV     ECX,[EAX]           
    MOV     DL,1
    CALL    dword ptr [ECX].vmtDestroy  // Call cleanup code (and destructor).
@@exit:
end;

调用FreeAndNil线程安全真的会破坏一个好的答案.如果您甚至在释放共享对象时认为自己需要线程安全,那么您的代码中的问题就会超出您希望FreeAndNil解决的问题. (12认同)

如上所述,在原始问题中,FreeAndNil()遗憾的是*不是*线程安全的,因为两个线程可以各自复制指针然后继续释放对象.FreeAndNil()应该使用Interlocked Variable Access(http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx). (5认同)

FreeAndNil不是线程安全的,应该将其编辑掉. (3认同)

FreeAndNil不会将nil分配给包含同一对象引用的所有其他变量.它只清除作为参数传递的指针.因此,对象可以同时分配和取消分配,如`Assigned(ObjectRef1)<> Assigned(ObjectRef2)`... :) (2认同)


Roddy.. 14

Delphi VCL'对象'实际上总是指向对象,但这个方面通常对你隐藏.只是释放对象使指针悬空,所以你应该使用FreeAndNil.

"Mysterious Assembler"大致翻译为:

if Obj != NIL then
  vmtDestroy(obj);  // which is basically the destructor/deallocator.

因为首先免费检查NIL,所以多次调用FreeAndNil是安全的......



1> Toon Krijthe..:

如果使用sl.Free,则释放对象但变量sl仍指向现在无效的内存.

使用FreeAndNil(sl)释放对象并清除指针.

顺便说一下,如果你这样做:

var
  sl1, sl2: TStringList;
begin
  sl1 := TStringList.Create;
  sl2 := sl1;
  FreeAndNil(sl1);
  // sl2 is still assigned and must be cleared separately (not with FreeAndNil because it points to the already freed object.)
end;




procedure TObject.Free;
asm
    TEST    EAX,EAX
    JE      @@exit              // Jump to exit if pointer is nil.
    MOV     ECX,[EAX]           
    MOV     DL,1
    CALL    dword ptr [ECX].vmtDestroy  // Call cleanup code (and destructor).
@@exit:
end;


调用FreeAndNil线程安全真的会破坏一个好的答案.如果您甚至在释放共享对象时认为自己需要线程安全,那么您的代码中的问题就会超出您希望FreeAndNil解决的问题.
如上所述,在原始问题中,FreeAndNil()遗憾的是*不是*线程安全的,因为两个线程可以各自复制指针然后继续释放对象.FreeAndNil()应该使用Interlocked Variable Access(http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx).
FreeAndNil不是线程安全的,应该将其编辑掉.
FreeAndNil不会将nil分配给包含同一对象引用的所有其他变量.它只清除作为参数传递的指针.因此,对象可以同时分配和取消分配,如`Assigned(ObjectRef1)<> Assigned(ObjectRef2)`... :)

2> Roddy..:

Delphi VCL'对象'实际上总是指向对象,但这个方面通常对你隐藏.只是释放对象使指针悬空,所以你应该使用FreeAndNil.

"Mysterious Assembler"大致翻译为:

if Obj != NIL then
  vmtDestroy(obj);  // which is basically the destructor/deallocator.

因为首先免费检查NIL,所以多次调用FreeAndNil是安全的......


...并将DL寄存器设置为1,以标记使用此方法调用Destroy并调用关联的AfterDestruction方法.
推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有