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