如何确定组件是否被销毁?

时间:2011-03-23 05:09:39

标签: delphi

我做了这个宣言:private...T:TTimer 现在当我在创建后释放T时,指针仍然保持不变,但只要目标对象被销毁,对该指针的任何操作都可能导致Invalida Pointer Operation所以我只想知道是否目标对象被破坏。我怎样才能做到这一点? (我不想使用FreeAndNil

2 个答案:

答案 0 :(得分:6)

Acually FreeAndNil是正确的解决方案,它可以检查你的对象是否分配(是否为零)为什么不使用它?

另一种方法是编写自己的“IsAssigned”或“IsValidObject”方法,该方法测试obejct的内部结构,以确定它是否真的存在或指针指向的垃圾。但这永远不会像FreeAndNil那样安全。

答案 1 :(得分:6)

一点背景。

指针和对象之间存在差异。

如果你有一个TTimer类型的变量(或字段),它的指针可以指向类TTimer的对象。为了使用它,您需要创建对象。

下面是这种情况的小内存映射(创建的对象)。

|------|
| T    | Contains address of object
|------|
|      |
       |
|
|      |
|------|
|object|
|      |
|------|

如果释放对象,则不释放指针。它只保留值,但对象不再存在(可能内存现在用于其他目的)。如果您尝试访问它,则会收到错误,因为您正在访问不属于您的内存。 内存映射如下所示:

|------|
| T    | Contains address of object
|------|
|      |
       |
|
|      |
|------|
|      |  Memory previously known as your object.
|      |
|------|

这就是你必须将指针设置为nil的原因,如果它有可能再次使用它。

请注意,将指针指定给同一类型的另一个变量时。两个指针都指向同一个对象。如果一个被释放(并且希望被填满),另一个现在指向未使用的内存。这就是为什么你必须小心重复指针。

如果您不想使用free和nil,则必须将指针设置为nil。或者您应该使用使用垃圾收集的语言。或者你可以使用第三种方式(但它可能比FreeAndNil更麻烦):

介绍智能指针:

TSmartPointer<T: class> = record
private
  FPointer: T;
  procedure SetPointer(const Value: T);
public
  class function Create(const APointer: T): TSmartPointer<T>; static;

  procedure Free;
  property Pointer: T read FPointer write SetPointer;
end;


class function TSmartPointer<T>.Create(const APointer: T): TSmartPointer<T>;
begin
  Result.FPointer := APointer;
end;

procedure TSmartPointer<T>.Free;
begin
  FPointer.Free;
  FPointer := nil;
end;

procedure TSmartPointer<T>.SetPointer(const Value: T);
begin
  if Value=nil then
    Free
  else
    FPointer := Value;
end;

你可以使用它:

var
  smart : TSmartPointer<TButton>;


smart := TSmartPointer<TButton>.Create(TButton.Create(nil));
try

finally
  smart.Free;
end;

或者:

smart := TSmartPointer<TButton>.Create(TButton.Create(nil));
try

finally
  smart.Pointer := nil;
end;

清除对象和指针。但FreeAndNil仍然是最好的解决方案。