Delphi - TObjectDictionary appears not freeing owned value - delphi

When I create TObjectDictionary with doOwnsValues and store TStringList as Value, after freeing the TObjectDictionary, I could still access the TStringList.
I modified the example given here:
Example for using Generics.Collections.TObjectDictionary
{$APPTYPE CONSOLE}
{$R *.res}
uses
Generics.Collections,
Classes,
System.SysUtils;
Var
MyDict : TObjectDictionary<String, TStringList>;
Sl : TStringList;
begin
ReportMemoryLeaksOnShutdown:=True;
try
//here i'm creating a TObjectDictionary with the Ownership of the
Values
//because in this case the values are TStringList
MyDict := TObjectDictionary<String, TStringList>.Create([doOwnsValues]);
try
//create an instance of the object to add
Sl:=TStringList.Create;
//fill some foo data
Sl.Add('Foo 1');
Sl.Add('Foo 2');
Sl.Add('Foo 3');
//Add to dictionary
MyDict.Add('1',Sl);
//add another stringlist on the fly
MyDict.Add('2',TStringList.Create);
//get an instance to the created TStringList
//and fill some data
MyDict.Items['2'].Add('Line 1');
MyDict.Items['2'].Add('Line 2');
MyDict.Items['2'].Add('Line 3');
//finally show the stored data
Writeln(MyDict.Items['1'].Text);
Writeln(MyDict.Items['2'].Text);
finally
//only must free the dictionary and don't need to worry for free the
TStringList assignated to the dictionary
MyDict.Free;
end;
Sl.Add('Foo added?');
Writeln(Sl[0]);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
I expect S1 should not have been accessible. Is it memory leak? or bug?

The string list object Sl has been freed by the dictionary. No memory is leaked. There is no bug in Delphi's RTL (the dictionary class) here.
Hence, when you do Sl.Add('Foo added?'); you are accessing an object that has been freed, and that is a bug in your code. You mustn't do that.
Just because you didn't get any visible symptoms of the bug this time doesn't mean it isn't a bug.
A simpler example:
type
TTest = class
Value: Integer;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Test: TTest;
begin
Test := TTest.Create;
try
Test.Value := 123;
finally
Test.Free;
end;
ShowMessage(Test.Value.ToString); // Bug!! Never do this!
end;
This is a bug. But chances are you might get a 123 message box anyway.
When you free an object, its memory area is declared as available so that other data might be stored there in the future. Thus, immediately after the destruction of your object, its bytes are likely intact where you left them. But eventually they will be overwritten with new data, and as time goes by, all bytes might change. You never know, and you shouldn't know: you don't own that part of the computer's memory any more.
Of course, destroying an object might do more than simply giving up its location in memory: OS handles might be closed, temporary files might be removed, etc. Hence, there are many things that might go wrong if you use a freed object, even if you use the object immediately after its destruction.
Even worse, the memory area of your old object might now partially or completely belong to new objects (or other kinds of data) in your application, so by accessing the members of your ghost object, you might be randomly changing bytes in these new objects. This might cause subtle random malfunction and errors and crashes at any later time in your application's life.
But you need not care about such details, because you'd never use a freed object anyway.
(Or, think of it this way: if you use a freed object, you are violating a contract, and basically anything can happen. One possibility is that nothing "strange" happens at all, but that is just dumb luck.)

Related

Scope and Lifetime of Inline Variables Declared in Nested Blocks, Do the scope apply for Objects as well?

Do i have to run FreeAndNil on the object later on to free the memory allocated for the object or it will be handled by the new scope functionality by delphi?
begin
var foo := TObject.Create();
end;
You still have to free the object manually, just as before.
The lifetime of the object has nothing to do with the scope of the variable. This has always been the case, and still applies. (Indeed, it is very much possible to create an object without assigning it to a variable at all.)
Even in this old-school example, the object would be leaked without the Free, even though the Bitmap variable goes out of scope at the procedure's end;.
procedure Test;
var
Bitmap: TBitmap;
begin
Bitmap := TBitmap.Create;
try
// use the bitmap
finally
Bitmap.Free;
end;
end;
Without Bitmap.Free, the object would still exist on the heap (and it might continue to use any non-memory resources it has access to), even though you have misplaced your last pointer to it!

Why does this one PAnsiChar get chopped when converted to AnsiString?

Please consider the following program:
program SO41175184;
{$APPTYPE CONSOLE}
uses
SysUtils;
function Int9999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString(IntToStr(9999)));
end;
function Int99999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString(IntToStr(99999)));
end;
function Int999999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString(IntToStr(999999)));
end;
function Str9999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString('9999'));
end;
function Str99999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString('99999'));
end;
function Str999999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString('999999'));
end;
begin
WriteLn(Int9999); // '9999'
WriteLn(Int99999); // '99999'
WriteLn(Int999999); // '999999'
WriteLn(string(AnsiString(Str9999))); // '9999'
WriteLn(string(AnsiString(Str99999))); // '99999'
WriteLn(string(AnsiString(Str999999))); // '999999'
WriteLn(string(AnsiString(PAnsiChar(AnsiString(IntToStr(9999)))))); // '9999'
WriteLn(string(AnsiString(PAnsiChar(AnsiString(IntToStr(99999)))))); // '99999'
WriteLn(string(AnsiString(PAnsiChar(AnsiString(IntToStr(999999)))))); // '999999'
WriteLn(string(AnsiString(Int9999))); // '9999'
WriteLn(string(AnsiString(Int99999))); // '9999' <----- ?!
WriteLn(string(AnsiString(Int999999))); // '999999'
ReadLn;
end.
Only in one of these cases does the string lose a single character, in Delphi 2010 and Delphi XE3 both. With FPC the same program works correctly. Switching to PChar also makes the problem disappear.
I suppose it has something to do with memory management, but I don't have enough of a clue where to look to do a meaningful investigation. Could anyone clarify?
Dynamically created strings are reference counted and deallocated when no references remain.
Result := PAnsiChar(AnsiString(IntToStr(99999)));
causes a temporary AnsiString to be created, its address taken via the cast to PAnsiChar, and then the temporary string deallocated†. The resulting pointer points to now-unclaimed memory that may be overwritten for pretty much any reason, including during the allocations of more strings.
Neither Delphi nor FPC clears memory by default during deallocations, so if the memory hasn't been re-used yet, you may get lucky when reading what used to be there. Or, as you saw, you may not.
When returning PAnsiChar like this, you need an agreement between caller and callee on memory management. You need to make sure you do not free the memory early, and you need to make sure your callers know how to free the memory afterwards.
† Remy Lebeau points out that this deallocation happens when the procedure or function returns. If there is another statement after the assignment to Result, the string will still be available. This is normally correct, but there are also cases where it the temporary string gets deallocated before the return, for example when you create temporary strings in a loop. I would not recommend using temporary objects after the statement that creates them concludes, even in cases where it is valid, because it makes it too hard to verify whether the code is correct. For those cases, just use an explicit variable.

Is there a way to instantiate a desired number of objects in Delphi, without iterating?

I think that C++ supports something on the lines of :
Object objects[100];
This would instantiate a 100 objects, right? Is it possible to do this in Delphi (specifically 2007)? Something other than:
for i:=0 to 99 do
currentObject = TObject.Create;
or using the Allocate function, with a passed size value a hundred times the TObject size, because that just allocates memory, it doesn't actually divide the memory and 'give' it to the objects.
If my assumption that the c++ instantiation is instant rather than under-the-hood-iterative, I apologize.
What you are looking for is impossible because
Delphi does not support static (stack allocated) objects.
Delphi objects do not have default constructors that can be automatically invoked by compiler.
So that is not a lack of 'sugar syntax'.
For the sake of complete disclosure:
Delphi also supports legacy 'old object model' (Turbo Pascal object model) which allows statically allocated objects;
Dynamic object allocation itself does not prevent automatic object instantiation syntax, but makes such a syntax undesirable;
Automatic object instantiation syntax is impossible because Delphi does not have default constructors: Delphi compiler never instantiate objects implicitly because it does not know what constructor to call.
While you can't do what you want using objects, if your objects are relatively simple, you may be able to get what you want by using an array of records.
Records in Delphi can have properties (including setters and getters), and class and instance methods. They are created automatically when declared, so declaring an array of them will create them all without iterating.
For more info: http://docwiki.embarcadero.com/RADStudio/XE3/en/Structured_Types#Records_.28advanced.29.
(I'm not sure when the new functionality was added to Delphi, it may well be after the 2007 version).
I don't know of any non-hacky way to do this besides iterating:
var
MyObjects: array[0..99] of TMyObject;
i: Integer;
begin
for i := 0 to 99 do
MyObjects[i] := TMyObject.Create;
end;
That declaration wouldn't create 100 objects, it would just give you an array of 100 object references that point to nothing useful.
Creating an object is a two step process. The first step is allocating memory (which your code also doesn't), the second step is calling the constructor (Create method) to initialize that memory, create additional objects, etc, etc.
The allocation part can be done without the loop, but the constructor needs to be called to intialize each instance.
Many VCL classes don't have an additional constructor. They just have the empty constructor that does nothing. In that case, there is no need to call it.
For instance, to fetch an array of stringlists, you can use the following code, adjusted from this example:
type
TStringListArray = array of TStringList;v
var
Instances: array of Byte;
function GetStringLists(Number: Integer): TStringListArray;
var
i: Integer;
begin
// Allocate instance memory for all of them
SetLength(Instances, Number * TStringList.InstanceSize);
// Zero the memory.
FillChar(Instances[0], Length(Instances), 0);
// Allocate array for object references.
SetLength(Result, Number);
for i := 0 to High(Result) do
begin
// Store object reference.
Result[i] := #Instances[i * TStringList.InstanceSize];
// Set the right class.
PPointer(Result[i])^ := TStringList;
// Call the constructor.
Result[i].Create;
end;
end;
And to get an array of 100 stringlists:
var
x: TStringListArray;
begin
x := GetStringLists(100);
So while this procedure may save you a neglectable amount of time, and may theoretically be more memory-efficient (less fragmentation), you will still need the loop. No easy way out.
It is somewhat possible in Delphi (but is not very practical in a Delphi environment, unless you are writing a custom memory manager). Creating an object instance is a two-step process - allocating memory for the object, and constructing the object's members inside of that memory. There is nothing requiring the memory of a given object to be allocated individually. You can allocate a larger block of memory and construct multiple objects inside of that block, taking advantage of a feature of Delphi that calls a constructor like a normal method if it is called from an instance variable instead of a class type, eg:
var
objects: array of Byte;
obj: TSomeClass;
begin
SetLength(objects, 100 * TSomeClass.InstanceSize);
FillChar(objects[0], 0, Length(objects));
for i := 0 to 99 do
begin
obj := TSomeClass.InitInstance(#objects[i * TSomeClass.InstanceSize]));
obj.Create;
end;
...
for i := 0 to 99 do
begin
obj := TSomeClass(#objects[i * TSomeClass.InstanceSize]);
obj.CleanupInstance;
end;
SetLength(objects, 0);
end;
This is not much different than what C++ does behind the scenes when declaring an array of object instances, only C++ supports declaring the array statically and it will call the constructors and destructors automatically, whereas Delphi does not support that.
There are a number of third-party implementations that allow you to allocate objects on the stack or in user-defined buffers, such as:
Objects on the Stack: A Delphi Relic
Allocate objects on stack, at specified memory address, or through any memory manager
Just to name a couple.

Is it memory safe to provide an object as a function result?

Here I provide simple piece of code.
function GetStringList:TStringList;
var i:integer;
begin
Result:=TStringList.Create;
Result.Add('Adam');
Result.Add('Eva');
Result.Add('Kain');
Result.Add('Abel');
end;
procedure ProvideStringList(SL:TStringList);
var i:integer;
Names:TStringList;
begin
Names:=TStringList.Create;
Names.Add('Adam');
Names.Add('Eva');
Names.Add('Kain');
Names.Add('Abel');
SL.Assign(Names);
Names.Free;
end;
procedure TForm1.btn1Click(Sender: TObject);
var SL:TStringList;
i:integer;
begin
SL:=TStringList.Create;
SL.Assign(GetStringList);
for i:=0 to 3 do ShowMessage(SL[i]);
SL.Free;
end;
procedure TForm1.btn2Click(Sender: TObject);
var SL:TStringList;
i:integer;
begin
SL:=TStringList.Create;
ProvideStringList(SL);
for i:=0 to 3 do ShowMessage(SL[i]);
SL.Free;
end;
And now the question: what will happen to result object in function GetStringList:Tstringlist, which is created, but never freed? (I call 2 times Create and only 1 time Free)
Is it memory safe to provide objects by function or should I use procedures to do this task, where object creation and destroying is simply handled (procedure ProvideStringlist)? I call 2 times Create and 2 times Free.
Or is there another solution?
Thanx in advance
Lyborko
Is it memory safe to provide an object as a function result?
It is possible, but it needs attention from the implementor and the call.
Make it clear for the caller, the he controls the lifetime of the returned object
Make shure you don't have a memory leak when the function fails.
For example:
function CreateBibleNames: TStrings;
begin
Result := TStringList.Create;
try
Result.Add('Adam');
Result.Add('Eva');
Result.Add('Kain');
Result.Add('Abel');
except
Result.Free;
raise;
end;
end;
But in Delphi the most commen pattern for this is:
procedure GetBibleNames(Names: TStrings);
begin
Names.BeginUpdate;
try
//perhaps a Names.Clear here
//but I don't use it often because the other
//way is more flexible for the caller
Names.Add('Adam');
Names.Add('Eva');
Names.Add('Kain');
Names.Add('Abel');
finally
Names.EndUpdate;
end;
end;
so the caller code can look like this:
procedure TForm1.btn1Click(Sender: TObject);
var
Names: TStrings;
i:integer;
begin
Names := CreateBibleNames;
try
for i := 0 to Names.Count -1 do
ShowMessage(Names[i]);
finally
Names.Free;
end;
end;
and the other, more common version:
procedure TForm1.btn1Click(Sender: TObject);
var
Names: TStrings;
i:integer;
begin
Names := TStringList.Create;
try
GetBibleNames(Names);
for i := 0 to Names.Count -1 do
ShowMessage(Names[i]);
finally
Names.Free;
end;
end;
(I have no compiler at the moment, so perhaps there are some errors)
I don't know what you mean by safe, but it is common practice. The caller of the function becomes responsible for freeing the returned object:
var
s : TStringList;
begin
s := GetStringList;
// stuff
s.free;
end;
Memory safety is a stricter variant of type safety. For memory safety, you typically need a precise garbage collector and a type system which prevents certain kinds of typecasts and pointer arithmetic. By this metric, Delphi is not memory safe, whether you write functions returning objects or not.
These are the very kinds of questions I grappled with in my early days of Delphi. I suggest you take your time with it:
write test code with debug output
trace your code step-by-step
try different options and code constructs
and make sure you understand the nuances properly;
The effort will prove a great help in writing robust code.
Some comments on your sample code...
You should get into the habit of always using resource protection in your code, even in simple examples; and especially since your question pertains to memory (resource) protection.
If you name a function GetXXX, then there's no reason for anyone to suspect that it's going to create something, and they're unlikely to protect the resource. So careful naming of methods is extremely important.
Whenever you call a method that creates something, assume it's your responsibility to destroy it.
I noticed some code that would produce Hints from the compiler. I recommend you always eliminate ALL Hints & Warnings in your programs.
At best a Hint just means some arbitrary redundant code (excesses of which make maintenance more difficult). More likely it implies you haven't finished something, or rushed it and haven't finished testing/checking.
A Warning should always be taken seriously. Even though sometimes the compiler's concern is a logical impossibility in the specific situation, the warning may indicate some subtle language nuance that you're not aware of. The code can always be rewritten in a more robust fashion.
I have seen many examples of poor resource protection where there is a compiler warning giving a clue as to the problem. So check them out, it will aid in the learning.
If an exception is raised in a method that returns a new object, care should be taken to ensure there isn't a memory leak as a result.
//function GetStringList:TStringList;
function CreateStringList:TStringList; //Rename method lest it be misinterpreted.
//var i: Integer; You don't use i, so why declare it? Get rid of it and eliminate your Hints and Warnings!
begin
Result := TStringList.Create;
try //Protect the memory until this method is done; as it can **only** be done by **this** method!
Result.Add('Adam');
Result.Add('Eva');
Result.Add('Kain');
Result.Add('Abel');
except
Result.Destroy; //Note Destroy is fine because you would not get here if the line: Result := TStringList.Create; failed.
raise; //Very important to re-raise the exception, otherwise caller thinks the method was successful.
end;
end;
A better name for the following would be PopulateStringList or LoadStringList. Again, resource protection is required, but there is a simpler option as well.
procedure ProvideStringList(SL:TStringList);
var //i:integer; You don't use i, so why declare it? Get rid of it and eliminate your Hints and Warnings!
Names:TStringList;
begin
Names:=TStringList.Create;
try //ALWAYS protect local resources!
Names.Add('Adam');
Names.Add('Eva');
Names.Add('Kain');
Names.Add('Abel');
SL.Assign(Names);
finally //Finally is the correct choice here
Names.Free; //Destroy would also be okay.
end;
end;
However; in the above code, creating a temporary stringlist is overkill when you could just add the strings directly to the input object.
Depending on how the input stringlist is used, it is usually advisable to enclose a BeginUpdate/EndUpdate so that the changes can be handled as a batch (for performance reasons). If your method is general purpose, then you have no idea of the origin of the input, so you should definitely take the precaution.
procedure PopulateStringList(SL:TStringList);
begin
SL.BeginUpdate;
try //YES BeginUpdate must be protected like a resource
SL.Add('Adam');
SL.Add('Eva');
SL.Add('Kain');
SL.Add('Abel');
finally
SL.EndUpdate;
end;
end;
our original code below had a memory leak because it called a method to create an object, but did not destroy. However, because the method that created the object was called GetStringList, the error is not immediately obvious.
procedure TForm1.btn1Click(Sender: TObject);
var SL:TStringList;
i:integer;
begin
//SL:=TStringList.Create; This is wrong, your GetStringList method creates the object for you.
//SL.Assign(GetStringList);
SL := CreateStringList; //I also used the improved name here.
try //Don't forget resource protection.
for i:=0 to 3 do ShowMessage(SL[i]);
finally
SL.Free;
end;
end;
The only error in your final snippet was the lack of resource protection. The technique used is quite acceptable, but may not be ideally suited to all problems; so it helps to also be familiar with the previous technique.
procedure TForm1.btn2Click(Sender: TObject);
var SL:TStringList;
i:integer;
begin
SL:=TStringList.Create;
try //Be like a nun (Get in the habit)
ProvideStringList(SL);
for i:=0 to 3 do ShowMessage(SL[i]);
finally
SL.Free;
end;
end;
No, it is not "memory safe". When you create an object, someone has to free it.
Your first example leaks memory:
SL:=TStringList.Create;
SL.Assign(GetStringList); // <-- The return value of GetStringList is
// used, but not freed.
for i:=0 to 3 do ShowMessage(SL[i]);
SL.Free;
The second example works fine, but you don't have to create and free an additional temporary instance (Names)
In general, the second example is slightly better, because it is obvious, who is responsible for the creation and destruction of the list. (The caller) In other situations, a returned object must be freed by the caller or perhaps it's forbidden. You can't tell from the code. If you must do so, it's good practice to name your methods accordingly. (CreateList is better than GetList).
It is the usage that is the leak, not the construct itself.
var sl2 : TStringlist;
sl2:=GetStringList;
sl.assign(sl2);
sl2.free;
is perfectly fine, or easier even,
sl:=getstringlist;
// no assign, thus no copy, one created one freed.
sl.free;
In btn1Click you should do:
var sl2: TStringList;
sl2 := GetStringList:
SL.Assign(sl2);
sl2.Free;
In btn2Click you don't have to create an instance of SL before calling ProvideStringList to not create a memory leak.
I use a combination of both idioms. Pass the object as an optional parameter and if not passed, create the object. And in either case return the object as the function result.
This technique has (1) the flexibility of the creation of the object inside of the called function, and (2) the caller control of the caller passing the object as a parameter. Control in two meanings: control in the real type of the object being used, and control about the moment when to free the object.
This simple piece of code exemplifies this idiom.
function MakeList(aList:TStrings = nil):TStrings;
var s:TStrings;
begin
s:=aList;
if s=nil then
s:=TSTringList.Create;
s.Add('Adam');
s.Add('Eva');
result:=s;
end;
And here are three different ways to use it
simplest usage, for quick and dirty code
var sl1,sl2,sl3:TStrings;
sl1:=MakeList;
when programmer wants to make more explicit ownership and/or use a custom type
sl2:=MakeList(TMyStringsList.create);
when the object is previously created
sl3:=TMyStringList.Create;
....
MakeList(sl3);

How can I check whether an object reference is still valid?

I have an issues where I am trying to determine if a reference to an object is valid. But it seems to be returning strange results.
procedure TForm1.Button1Click(Sender: TObject);
var form1 : TForm;
ref2 : TControl;
begin
form1 := TForm.Create(nil);
form1.Name := 'CustomForm';
form1.Parent := self; //Main Form
form1.Show;
ref2 := form1;
showmessage(ref2.ClassName+' - '+ref2.Name+' - '+BoolToStr(ref2.visible,true));
freeandnil(form1);
showmessage(ref2.ClassName+' - '+ref2.Name+' - '+BoolToStr(ref2.visible,true));
end;
The first showmessage returns - "TForm - CustomForm - True" (Just like I would expect it to).
The second showmessage return - "TForm - - False". I was actually hoping for some kind of access violation that I could then trap and know that the reference isn't valid.
In my application I need to compile a list of random TForm descendants as they are created and then check later if they have gone away (or are not visible). Unfortunately it is a plugin based system so I can go change all of these Forms to post a "I'm done Message."
Would code like this be safe to use (assuming I actually am checking for access violations)? Does anybody have any ideas what is happening.
Thanks
The problem is that with a certain likelyhood the memory accessed is still reserved by the Delphi memory manager. In that case Windows does not generate any kind of access violation, because that memory belongs to you!
One possibility is to switch to a different Delphi memory manager which can detect the use of freed objects. FastMM4, for example, has several "memory hygiene" checks, which are very useful for debugging, but even then you won't catch all of these errors immediately.
You can download FastMM4 from SourceForge.
Any TComponent (e.g. a TForm descendant) can register for notifications when other components are destroyed.
In your form, call FreeNotification(form) for each form that you wish to be notified of the destruction of. Then on the same form override the Notification() method. When any form (or other component) for which you have called FreeNotification() is destroyed, your Notification() method will be called with a Component parameter referencing the form and an Operation of opRemove.
If I've understood what it is you are trying to achieve, I think this should be enough information to devise an approach to do what you need.
After
freeandnil(form1);
the Delphi memory manager just marks the memory allocated by form1 as free, but all form1 data is still there, and can be accessed via ref2 until the memory manager reuse the freed memory for some other object(s).
You can't check that way if ref2 references a valid object or not. Code like this can't be safe, it is actually a bug.
If you want to obtain a 100% access violation modify the code as follows (here ref2^ = nil if form1 is freed):
procedure TForm1.Button1Click(Sender: TObject);
var form1 : TForm;
ref2 : ^TControl;
begin
form1 := TForm.Create(nil);
form1.Name := 'CustomForm';
form1.Parent := self; //Main Form
form1.Show;
ref2 := #form1;
showmessage(ref2^.ClassName+' - '+ref2^.Name+' - '+BoolToStr(ref2^.visible,true));
freeandnil(form1);
showmessage(ref2^.ClassName+' - '+ref2^.Name+' - '+BoolToStr(ref2^.visible,true));
end;
There is no reliable way to do what you are trying to do using the technique you're attempting. Forms that have "gone away" may have their memory reused, possibly even for a new form.
At best, you could work some mechanism whereby you cache the results of iterating Screen.Forms, but you can still fall foul of accidental duplicates, where a form gets destroyed and another gets reallocated and gets the same object address. That scenario is less likely than the memory being reused for some other object, however.
In a similar case I am using a singleton object that keeps a list of all the created forms.
Each form has a field with a reference to this Object.
TMyForm = class(TForm)
private
//*** This is the reference to the singleton...
FFormHandler: TFormHandler;
public
...
//*** you might want to publish it as a property:
property FormHandler: TFormHandler read FFormHandler write FFormHandler;
end;
You can set this reference e.g. when calling the constructor:
TMyForm.Create(aFormHandler: TFormHandler; aOwner: TComponent)
begin
FFormHandler := aFormHandler;
inherited Create(aOwner);
end;
(Or you could set the field from outside directly after creating the form if you don't want to change the parameters of the constructor).
When the form ist destroyed it notifies the handler and tells him to remove the form from the list - something like that:
TMyForm.Destroy(Sender: TObject);
begin
FFormHandler.RemoveFromFormList(Self);
inherited;
end;
(The details of the track-keeping are not included in the expample - e.g. a method "AddToFomList" or something alike would be needed)
There is one very interesting memory manager. It is called SafeMM: http://blogs.embarcadero.com/medington/2009/10/16/24839 But still it is for debugging only.
Given that you cannot modify the code that is out there in the plugins, all the good solutions about how to write safer code are not applicable to your case.
You have 1 way of doing it by
checking if an Object reference is
still what it's supposed to be by
looking up the VMT. This idea was
first published by Ray Lischner (who advocated for FreeAndNil for that very reason) and
later by Hallvard Vassbotn: see
this SO answer.
Another, better but introducing major slowdown, is to use FastMM4 in FullDebugmode to have it to replace all the freed objects by a TFreeObject instance instead of simply releasing the memory to the available pool.
Note that both methods do not prevent a false positive if another instance of the same class happens to be created at the same memory address. You get a valid object of the right type, just not the original one. (Unlikely in your case, but possible)
it is as simple as comparing against NIL:
// object declaration
Type object;
object = new Type();
...
// here you want to be sure of the existance of the object:
if (object <> nil )
object.free;
If you cannot test in another manner, you can use this as a last resort±
function IsValidClass( Cls: TClass ): Boolean;
var
i: Integer;
begin
for i := 0 to 99 do begin
Result := ( Cls = TObject ); // note that other modules may have a different root TObject!
if Result then Exit;
if IsBadReadPtr( Cls, sizeof( Pointer ) ) then Break;
if IsBadReadPtr( Pointer( Integer( Cls ) + vmtParent ), sizeof( Pointer ) ) then Break;
Cls := Cls.ClassParent;
end;
Result := False;
end;
function IsValidObject( Obj: TObject ): Boolean;
begin
Result := not IsBadReadPtr( Obj, sizeof( Pointer ) ) and IsValidClass( Obj.ClassType ) and not IsBadReadPtr( Obj, Obj.InstanceSize );
end;
IsBadReadPtr comes from Windows.

Resources