开发者

How to determine whether or not the component is destroyed?

I made this declaration: private...T:TTimer Now when I free T after creation the pointer still remains for su开发者_开发知识库re, but as long as the target object is destroyed, any operation on this pointer may cause Invalida Pointer Operation so I just want to know whether or not the target object is destroyed. How can I do this? (I don't want to use FreeAndNil)


A little background.

There is a difference between pointers and objects.

If you have a variable (or field) of type TTimer, its a pointer which can be pointed to an object of class TTimer. In order to use it you need to create the object.

Below is a small memory map of this situation (a created object).

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

If you free the object, you don't free the pointer. It just keeps the value, but the object isn't there anymore (likely the memory is used for other purposes now). If you try to access it, you get an error because you are accessing a piece of memory which isn't yours. The memory map looks like:

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

This is the reason why you have to set the pointer to nil if there is even a slight chance that it can be used again.

Note that when you assign a pointer to another variable of the same type. Both pointers point to the same object. If one is freed (and hopefully nilled) the other now points to the unused memory. That's why you have to be careful with duplicating pointers.

If you don't want to use free and nil, you have to set the pointer to nil yourself. Or you should use a language that uses garbage collection. Or you could use a third way (but its maybe more hassle than FreeAndNil):

Introducing the smart pointer:

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;

You can use this like:

var
  smart : TSmartPointer<TButton>;


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

finally
  smart.Free;
end;

Or:

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

finally
  smart.Pointer := nil;
end;

Both clear object and pointer. But FreeAndNil is still the best solution.


Acually FreeAndNil is the right solution for this, it would be the way to check if your Object Assigned or not (is nil ornot) why not use it?

The alternative way would be to write your own "IsAssigned" or "IsValidObject" method which tests the internal structure of the obejct to decide if its really there or is it garbage what the pointer points to. but this will never be as safe as FreeAndNil.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜