Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi 2009 - Can an Interface Property Cause a Memory Leak?

I inherited an Intraweb app that had a 2MB text file of memory leaks as reported by FastMM4. I've got it down to 115 instances of one class leaking 52 bytes.

A brief description of the bad actor is:

TCwcBasicAdapter = class(TCwcCustomAdapter)  
  protected  
    FNavTitleField: TField;  
    function GetAdapterNav(aDataSet: TDataSet): ICwcCDSAdapterNav; override;  
  public  
    constructor Create(aDataSource: TDataSource; aKeyField, aNavTitleField: TField; aMultiple: boolean);  
  end;  

and the interface is:

  ICwcCDSAdapterNav = interface(IInterface)  

Am I barking up the wrong tree, since the property is reference counted? Are there any circumstances where the interface property could keep the class from being destroyed?

Here is the implementation of the method above:

function TCwcBasicAdapter.GetAdapterNav(aDataSet: TDataSet): ICwcCDSAdapterNav;
var
  AdapterNav: TCwcCDSAdapterNavBase;
begin
  result := nil;
  if Assigned(aDataSet) then begin
    AdapterNav := TCwcCDSAdapterNavBasic.Create(aDataSet, FKeyField.Index, FNavTitleField.Index);
    try
      AdapterNav.GetInterface(ICwcCDSAdapterNav, result);
    except
      FreeAndNil(AdapterNav);
      raise;
    end;
  end;
end;

with the class declared as:

TCwcCDSAdapterNavBase = class(TInterfacedObject, ICwcCDSAdapterNav)
like image 564
user122603 Avatar asked Dec 29 '22 21:12

user122603


2 Answers

FastMM should give you what is leaked and where it was created.
That would help narrowing it down to the real culprit: who is leaking what?

I'm not sure what really your question is?
Your code is incomplete or not the one in question: your class does not have an Interface property nor an Interface private Field, just a method that returns an Interface, which is harmless.

Edit: Without seeing the code of your Object implementing ICwcCDSAdapterNav, we can't tell if it is indeed reference counted.
If you don't descend from TInterfacedObject, chances are that it's not reference counted and that you cannot rely on this automagically freeing...

You may want to give a look at this CodeRage 2 session: Fighting Memory Leaks for Dummies. It mainly shows how to use FastMM to prevent/detect memory leaks in Delphi. Was for D2007 but still relevant for other versions.

like image 150
Francesca Avatar answered Jan 13 '23 13:01

Francesca


You've got some good answers so far about how FastMM works. But as for your actual question, yes, interfaced objects can leak in two different ways.

  1. Interfaces are only reference-counted if the objects they belong to have implemented reference counting in their _AddRef and _Release methods. Some objects don't.
  2. If you have circular interface references, (Interface 1 references interface 2, which references interface 1,) then the reference count will never fall to 0 without some special tricks on your part. If this is your problem, I'll refer you to Andreas Hausladen's recent blog post on the subject.
like image 24
Mason Wheeler Avatar answered Jan 13 '23 12:01

Mason Wheeler