Reputation: 517
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
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:
TComponent
as base class - where you can use its notification system to get notifications when object instance is going to be destroyedNote: 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