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.
Related
Say my form is delared as TFormOther = class(TForm, IMyInterface) where
type
IMyInterface = interface
['{50E7E215-A8EA-4A1C-9F1E-018E4A76DCBD}']
procedure DoSomething;
end;
and
TFactory = class(TInterfacedObject)
public
procedure MakeIt;
end;
procedure TFactory.MakeIt;
var
LMyIntf: IMyInterface;
begin
LMyIntf := TFormOther.Create(nil);
LMyIntf.DoSomething;
// (LMyIntf as TFormOther).Free; This is wrong and gives the classic:
// FastMM has detected an attemp to use an interface of a freed object.
end;
If I don't free the TFormOther instance I leak memory.
I know I can do Action := TCloseAction.caFree in TFormOther.FormClose but is that the only and best way?
This Will an interface-implementing form free itself when there are no more references to it? helped a lot but did not say how one should free the form.
Problem with directly freeing form through its interface reference with (LMyIntf as TFormOther).Free; is that interface reference will outlive form object instance.
When that interface goes out of scope, in the procedure epilogue, compiler inserted call to _IntfClear to finalize LMyIntf reference will eventually end up calling _Release method on already destroyed form instance.
To avoid such scenario, you must explicitly clear the interface before you can free form. This requires additional object variable through which you can call Free to free the form.
procedure TFactory.MakeIt;
var
LMyIntf: IMyInterface;
LObj: TObject;
begin
LMyIntf := TFormOther.Create(nil);
LMyIntf.DoSomething;
LObj := TObject(LMyIntf);
LMyIntf := nil;
LObj.Free;
end;
When it comes to releasing the form through FromClose event handler, such release will work flawlessly only if there are no active interface references to the form at the time of the release. It is hard to say which approach is better when discussing general code, but when using FormClose event it might be harder to ensure that you don't have active interface at that moment and such code may be harder to follow.
I'm correcting some (a lot) memory leaks of a project. I have some Delphi experience but is not my main language so I'm extra careful at freeing stuff.
I've already tried it and everything looks fine, but I thought that it would free the Field too (not what I want). Does that happen just with Objects?
TMainObject = class(TObject)
public
FDoubleField : double;
*
*
*
procedure TMainObject.CalculateSomeFieldValue();
var
lAux : TAuxObject;
begin
lAux := TAuxObject.Create;
lAux.RecoverData;
if **some condition** then
begin
FDoubleField := lAux.DoubleProperty;
end
else
begin
FDoubleField := lAux.OtherDoubleProperty;
end;
FreeAndNil(lAux);
end
Thanks in advance
Edit: I do not want to lose FDoubleField because I will use it later, but I need to free lAux.
The FDoubleField field doesn't need to be freed because it will be automatically "freed" as soon it goes out of scope.
Some tips:
You don't need to use FreeAndNil(lAux) in this case, just use lAux.Free because there's no need to set a pointer to nil which will no longer be used.
At the beginning, you can set ReportMemoryLeaksOnShutDown := True (documentation). In this way, you will be notified about any memory leak when the application closes.
Use try-finally blocks for being sure to always free the object you created
Modified code using try-finally block and Free:
procedure TMainObject.CalculateSomeFieldValue();
var
lAux : TAuxObject;
begin
lAux := TAuxObject.Create;
try
lAux.RecoverData;
if **some condition** then
begin
FDoubleField := lAux.DoubleProperty;
end
else
begin
FDoubleField := lAux.OtherDoubleProperty;
end;
finally
lAux.Free;
end;
end
In the example you give, you don't need to free anything for a variable of type double in a class (Also called a "field").
Field that must be freed are classes or simple pointers of any type that have been allocated.
The normal place to free data in a class is in the destructor.
Also pay attention to interfaces. They are generally reference counted and as such MUST NOT be freed. Frequently, interfaces are assigned a value by calling a class constructor and you must really look if the value returned by the class constructor is assigned to a variable of an interface type or to a variable of some object type. Assuming TAuxObject also implement the interface IAuxInterface, your have the following valid code:
var
AuxObj : TAuxObject;
AuxIntf : IAuxInterface;
begin
AuxIntf := TAuxObject.Create; // This one must NOT be freed
AuxObj := TAuxObject.Create; // This one must be freed
try
....
finally
AuxObj.FRee;
end;
end;
Properly using interfaces is a big subject. There are cases where interfaces are not reference counted.
There are in Delphi libraries a few classes designed to be ancestor for object supporting interface (For example TInterfacedObject). This ancestor implement reference counting properly (Methods QueryInterface, _AddRef and _Release). If your object do no derive from a class already implementing reference counting, then if you need reference counting then you must implement methods QueryInterface, _AddRef and _Release. As soon as they are defined, some compiler magic will call them when it is needed. And by the way freeing the object must actually done by the _Release method implementation.
Things becomes even more complex if the developer make use of weak and unsafe keywords to mark the interface type variable.
I am currently testing two external COM components. I have big issue with one of them, but I cannot really find reason behind such behavior. Let me provide some example.
const
CLASS_SomeClas: TGUID = '{SomeGUID}';
type
ISomeInterface = interface(IDispatch)
['{SomeGUID}']
function SomeMethod(const AInput: WideString): WideString; safecall;
end;
TWrappingClass = class(TObject)
strict private
FInstance: ISomeInterface;
procedure CreateInstance;
public
procedure DoYourActualJob;
end;
procedure TWrappingClass.CreateInstance;
begin
FInstance := CreateComObject(CLASS_SomeClass) as ISomeInterface;
dbg(FInstance._AddRef); // Debugs 3
dbg(FInstance._AddRef); // Debugs 4
dbg(FInstance.Release); // Debugs 3
dbg(FInstance._AddRef); // Debugs 4
FInstance.SomeMethod(''); //Runs as expected
end;
procedure TWrappingClass.DoYourActualJob;
begin
CreateInstance;
dbg(FInstance._AddRef); //Debugs -1!
FInstance.SomeMethod(''); //AV
end;
As provided with example instance gets invalid after it leaves CreateInstance method. Component is designed to work with many sequential calls of SomeMethod and it does work when called inside single method.
Could someone give me clue what is actually happening there, why my instance gets invalid? Is it problem with my code, with Delphi or with component's code? When I change the implementation of TWrappingClass to another vendor (that is I change both ISomeInterface and CLASS_SomeClass) then everything works fine.
EDIT:
Behaviour does not change when I don't even call SomeMethod. That is after I leave CreateInstance, call to _AddRef returns -1. Component I am testing is here CadEditorX Probably I am not allowed to attach the OCX without violating its license.
You state clearly in the question that the erroneous behaviour only occurs with one specific COM object. Given this fact, and that Delphi's COM reference counting is known to work correctly, the only reasonable conclusion is that the fault lies in this specific COM object.
Your only recourse of action is to contact the vendor of this COM object and file a bug report with them.
One thing to look at, with a view to a possible work around, is how you are creating the object. You use CreateComObject. This receives a class ID and returns IUnknown. It calls CoCreateInstance passing the class ID, and requesting the IUnknown interface. You then need to query for your interface, ISomeInterface. So your code looks like this:
var
iunk: IUnknown;
intf: ISomeInteface;
....
CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER,
IUnknown, iunk);
iunk.QueryInterface(ISomeInterface, intf);
The fact that you have two interface variables, one IUnknown and one ISomeInterface explains why you see the reference count that you do. Now, you might think that you only have one interface variable, but that's not the case. There are two, only one of them is an implicit local. You can see this by looking at the compiled code and stepping through under the debugger.
This code:
procedure TWrappingClass.CreateInstance;
begin
FInstance := CreateComObject(CLASS_SomeClass) as ISomeInterface;
end;
is compiled as if it were this (ignoring error checking):
procedure TWrappingClass.CreateInstance;
var
iunk: IUnknown;
begin
iunk := CreateComObject(CLASS_SomeClass);
try
FInstance := CreateComObject(CLASS_SomeClass) as ISomeInterface;
finally
iunk := nil;
end;
end;
Perhaps the COM component cannot handle the call to Release made on its IUnknown interface.
So, you could try to work around this by using CoCreateInstance instead of CreateComObject. Pass ISomeInterface as the riid parameter.
OleCheck(CoCreateInstance(CLASS_SomeClass, nil, CLSCTX_INPROC_SERVER
or CLSCTX_LOCAL_SERVER, ISomeInterface, FInstance));
For one particular issue in the architecture of an application I'm working on, interfaces seem to be a nice solution. Specifically, some "business objects" depend on a bunch of settings that are pulled from the database in the actual app. Letting those business objects ask for an interface (through Inversion of Control), and letting a central TDatabaseSettings object implement those interfaces, allows for better isolation, and thus for much easier unit testing.
However, in Delphi, interfaces seem to come with an, in this case, unpleasant bonus: reference counting. This means that if I do something like this:
type
IMySettings = interface
function getMySetting: String;
end;
TDatabaseSettings = class(..., IMySettings)
//...
end;
TMyBusinessObject = class(TInterfacedObject, IMySettings)
property Settings: IMySettings read FSettings write FSettings;
end;
var
DatabaseSettings: TDatabaseSettings;
// global object (normally placed in a controller somewhere)
//Now, in some function...
O := TMyBusinessObject.Create;
O.Settings := DatabaseSettings;
// ... do something with O
O.Free;
On the last line (O.Free), my global DatabaseSettings object is now also freed, since the last interface reference to it (which was contained in O) is lost!
One solution would be to store the 'global' DatabaseSettings object with an interface; another solution would be to override the reference counting mechanism for the TDatabaseSettings class, so I can continue to manage the DatabaseSettings as a normal object (which is much more consistent with the rest of the app).
So, in summary, my question is: how do I disable the interface reference counting mechanism for a particular class?
I've been able to find some info that suggests overriding the IInterface methods _AddRef and _Release for the class (TDatabaseSettings in the example); has anyone ever done that?
Or would you say I shouldn't do this (confusing? just a bad idea?), and find a different solution to the architectural problem?
Thanks a lot!
Ok, you can bypass it, but the question is if you really want that.
If you want to use interfaces, you better use them completely. So as you have experienced it, you get problems if you mix class and interface variables.
var
// DatabaseSettings: TDatabaseSettings;
DatabaseSettings : IMySettings;
//Now, in some function...
O := TMyBusinessObject.Create;
O.Settings := DatabaseSettings;
// ... do something with O
O.Free;
You now have a second reference to the interface and losing the first will not free the object.
It as also possible to keep both the class and the object:
var
DatabaseSettings: TDatabaseSettings;
DatabaseSettingsInt : IMySettings;
Be sure to set the interface right after the object has been created.
If you really want to disable reference counting, you just have to create a new descendant of TObject that implements IInterface. I have tested the example below in D2009 and it works:
// Query Interface can stay the same because it does not depend on reference counting.
function TMyInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
constructor TMyInterfacedObject.Create;
begin
FRefCount := 1;
end;
procedure TMyInterfacedObject.FreeRef;
begin
if Self = nil then
Exit;
if InterlockedDecrement(FRefCount) = 0 then
Destroy;
end;
function TMyInterfacedObject._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TMyInterfacedObject._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
FreeRef just lowers the refcount just like _Release. You can use it where you normally use Free.
Don't descend from TInterfacedObject, instead descend from TSingletonImplementation from standard System.Generics.Defaults unit.
TSingletonImplementation is a base for simple classes that need a basic IInterface implementation, with reference counting disabled.
TSingletonImplementation is a thread-safe base class for Delphi classes that support interfaces. Unlike TInterfacedObject, TSingletonImplementation does not implement reference counting.
_AddRef, _Release and _QueryInterface are, in fact, what you want to override. You should be very clear about what you're doing, however, as this can cause memory leaks or strange, hard-to-find bugs.
Don't descend from TInterfacedObject, instead descend from TObject, and implement your own versions of the first two of those methods that return 1.
To disable reference counting, AddRef and Release should do nothing but return -1
function TMyInterfacedObject._AddRef: Integer;
begin
Result := -1;
end;
function TMyInterfacedObject._Release: Integer;
begin
Result := -1;
end;
There is quite a lot of utility in interfaces without reference counting. If you use reference counting, then you cannot mix object and interface references as bad things will happen. By disabling ref counts, you can happily mix interface and object references without worrying about your objects suddenly getting auto destroyed.
Disabling reference counting for this kind of problem smells bad.
A much nicer and architectural solution would be to use some kind of "singleton" pattern.
The easiest way to implement this would look like:
interface
type
TDatabaseSettings = class(..., IMySettings)
end;
function DatabaseSettings: IMySettings;
implementation
var
GDatabaseSettings: IMySettings;
function DatabaseSettings: IMySettings;
begin
if GDatabaseSettings = nil then GDatabaseSettings := TDatabaseSettings.Create;
Result := GDatabaseSettings;
end;
O := TMyBusinessObject.Create;
O.Settings := DatabaseSettings;
O.Free;
By the way: when you use interfaces: always use interface variables! Do not mix both class en interface vars (use "var Settings: IMySettings" instead of "var Settings: TDatabaseSettings"). Otherwise reference counting will get in your way (auto destroy, invalid pointer operations, etc).
In the above solution, GDatabaseSettings is also of type "IMySettings", so it gets a proper reference count, and will last till your program terminates.
Or just use the code below:
var
I: IMyInterface;
begin
I := ...;
...
Do whatever you want in a scope;
Initialize(I); //- this will clear the interface variable without calling the _release.
end.
Suppose my Delphi classes look like this:
interface
type
TMySubInfo = class
public
Name : string;
Date : TDateTime;
Age : Integer;
end;
TMyInfo = class
public
Name : string;
SubInfo : array of TMySubInfo;
destructor Destroy; override;
end;
implementation
destructor TMyInfo.Destroy;
begin
// hmmm..
end;
end.
To properly clean up, what should go in the destructor? Is it enough to do SetLength(SubInfo,0), or do I need to loop through and free each TMySubInfo? Do I need to do anything at all?
You need to loop through and free each created object.
You must know, that declaring a array of TMySubInfo doesn't actually create the objects. You have to create them later on.
I would use a TList instead for a more dynamic approach. You could even use a TObjectList that can free all its items when the list gets freed.
You should free each item, like this
destructor TMyInfo.Destroy;
var
I: Integer;
begin
for I:= Low(SubInfo) to High(SubInfo) do
SubInfo[I].Free;
SetLength(SubInfo, 0);
inherited;
end;
You free the objects the same way you allocated them. If you assigned an element's value by calling the constructor of a class, then free the object referenced by that element.
destructor TMyInfo.Destroy;
var
info: TMySubInfo;
begin
for info in SubInfo do
info.Free;
inherited;
end;
That uses syntax introduced in Delphi 2005. If you have an older version, use an explicit loop-control variable:
var
i: Integer;
begin
for i := 0 to High(SubInfo) do
SubInfo[i].Free;
You don't need to call SetLength at the end. A dynamic-array field like SubInfo gets released automatically when the object is destroyed. It works the same as interface, string, and Variant fields.
Agreed with all the above suggestions, but I want to add an (admittedly somewhat anal) recommendation that you always call the FreeAndNil() procedure in preference to the Free method.
Sooner or later you will accidentally access an object that you have already freed. If you have the habit of FreeAndNil-ing everything, then you get an immediate a/v on the line that contains the problem. If you merely Free'd the object, you will likely get a mysterious and apparently unconnected failure some time later...
This might seem obsessive in the context of a destructor, as here. Ok, it is a bit, but either one does it everywhere or not at all.
It is also anal, but Like to free in the reverse order to the creation, for example:
For I := List.Count-1 downto 0 do
List[I].Free;
I view creation and destruction as parethesis () although it makes litte actual execution diference.
Bri
If you created the objects via constructor calls, you need to make calls to Free to free them. If not, you don't.
For every new there should be a free.
Can you not use Finalize?