在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是安全的......
如果使用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;
Delphi VCL'对象'实际上总是指向对象,但这个方面通常对你隐藏.只是释放对象使指针悬空,所以你应该使用FreeAndNil.
"Mysterious Assembler"大致翻译为:
if Obj != NIL then vmtDestroy(obj); // which is basically the destructor/deallocator.
因为首先免费检查NIL,所以多次调用FreeAndNil是安全的......