Eric Cheng
Eric Cheng

Reputation: 517

How to check if an object is already destroyed or not?

  1. I have created an object
  2. I passed it to somewhere else as parameter. Somewhere else has Free the object which out of my control.
  3. At the end my coding, I try to check if the object is valid then destroy it. The Assigned() method returned true (seems it is because the variable storing the object reference address). However, the referenced object ready destroyed and I got an exception.

My question is, how could I check if an object is already destroyed? What else other than Assigned() can check the object still exists or not?

program Project1;
uses System.SysUtils;

type TObj = class
  public
    Name: string;
end;

var AnObj, AnObj2 : TObj;
begin
  try
    try
      AnObj := TObj.Create;
      AnObj.Name := 'Testing';

      AnObj2 := AnObj;     // AnObj passed to other procedures as param
      FreeAndNil(AnObj2);  // somewhere else "Free" the object out of my control
      // as a result, AnObj is still assigned but the object is destroyed
    finally
      if Assigned(AnObj) then // AnObj is assigned, HOW COULD I IMPROVE HERE?
        FreeAndNil(AnObj);    // Exception: Invalid pointer operation
    end;
  except
    on E:Exception do
      writeln(E.Message);
  end;
  readln;
end.

Upvotes: 1

Views: 3676

Answers (1)

Dalija Prasnikar
Dalija Prasnikar

Reputation: 28516

How to check if an object is already destroyed or not?

Short answer is you can't. There is no mechanism that will allow you to to check validity of object under manual memory management.

If you want to track validity for debugging purposes, you can use custom memory manager (like FastMM in full debug mode) that can track all references and will report when you access dangling pointers.


FreeAndNil in combination with Assigned only works when you have single reference to an object. If you have more it falls apart because FreeAndNil can nil only the reference you called it upon. All other references will become dangling pointers and Assigned cannot detect dangling pointers.

In a nutshell, Assigned works only when reference points to valid object instance or contains nil value. Under manual memory management you have to keep track and make sure that your reference always contains valid value if you need to use Assigned.

Using Assigned when you keep single reference to an object

If you have single reference to object, you can use Assigned for lazy initialization pattern where you will create object instance if it is not already created. But you have to make sure that object reference contains nil reference in the first place.

Object references will be automatically initialized to nil only if they are class fields, object instance fields or global variables.

If you don't plan to reuse that object reference once it is released you can use Free for releasing its memory.

If you have reusable reference, where you want to create and release object instance multiple times, you have to use FreeAndNil, or set reference to nil after you call Free. That is the only way you can ensure Assigned will work after object is released. Again, this Assigned/FreeAndNil pattern only works if you keep one and only one reference to that object.

Using Assigned when you keep multiple references to an object

If possible don't ever keep more than one reference to an object instance. If you have scenario where you really must keep multiple references to an object instance you need to implement some mechanism that will ensure you can notify all references that object is no longer valid.

There are several ways to do so:

  1. Using interfaces - their automatic memory management will prevent dangling pointers
  2. Using TComponent as base class - where you can use its notification system to get notifications when object instance is going to be destroyed
  3. Implement your own notification system to manage all references to an object instance

Note: For 2. and 3. you have to manually nil all references to an object when you get notification it will be destroyed. If you don't do that any reference you don't set to nil, will be invalid, dangling reference any using Assigned upon it will fail to work properly.


If you have situation when you passed object as parameter, and some code beyond your control called Free on that object then you are dealing with ownership transfer. You created the object, but then you transferred ownership (responsibility to release object) to some other code. After that you should not use that object reference again (except in some narrow scenarios, when you know for sure that immediate code after transfer is complete will not trigger object release).

You can use object reference you don't own (after you have transferred ownership) only if there is some notification mechanism (as mentioned earlier) that can notify you when object instance is released.

Also you should never, ever free objects you don't own. In your example, even if you can get notified that object is going to be destroyed all you can do is nil the reference that points to it. You should not attempt to release it.

Upvotes: 5

Related Questions