Question

J'ai hérité d'une application Intraweb contenant un fichier texte de 2 Mo contenant des fuites de mémoire, comme indiqué par FastMM4. Je l'ai descendue à 115 instances d'une classe ayant une fuite de 52 octets.

Une brève description du mauvais acteur est la suivante:

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

et l'interface est:

  ICwcCDSAdapterNav = interface(IInterface)  

Est-ce que je me trompe d'arborescence, puisque la propriété est comptée par référence? Existe-t-il des circonstances dans lesquelles la propriété interface pourrait empêcher la destruction de la classe?

Voici l'implémentation de la méthode ci-dessus:

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;

avec la classe déclarée comme:

TCwcCDSAdapterNavBase = class(TInterfacedObject, ICwcCDSAdapterNav)
Était-ce utile?

La solution

FastMM devrait vous indiquer ce qui a fui et où il a été créé.
Cela aiderait à le réduire au véritable coupable: qui fuit quoi?

Je ne sais pas quelle est vraiment votre question.
Votre code est incomplet ou ne correspond pas à celui en question: votre classe n'a pas de propriété Interface ni de champ privé d'interface, mais simplement une méthode qui renvoie une interface sans danger.

Modifier : sans voir le code de votre objet implémentant ICwcCDSAdapterNav, nous ne pouvons pas dire s'il s'agit bien d'une référence comptée.
Si vous ne descendez pas de TInterfacedObject , il est probable que ce ne soit pas une référence comptée et que vous ne puissiez pas compter sur cette libération automatique ...

Vous voudrez peut-être jeter un coup d'œil sur cette session CodeRage 2 : Lutte contre les fuites de mémoire pour les nuls . Il montre principalement comment utiliser FastMM pour prévenir / détecter les fuites de mémoire dans Delphi. Était pour D2007 mais toujours pertinent pour les autres versions.

Autres conseils

Vous avez jusqu'à présent de bonnes réponses sur le fonctionnement de FastMM. Mais pour ce qui est de votre question, oui, les objets interfacés peuvent fuir de deux manières différentes.

  1. Les interfaces ne sont comptées que si les objets auxquels elles appartiennent ont implémenté le comptage des références dans leurs méthodes _AddRef et _Release. Certains objets ne le font pas.
  2. Si vous avez des références d'interface circulaire ((Interface 1 fait référence à l'interface 2, qui fait référence à l'interface 1)), le nombre de références ne tombera jamais à 0 sans astuces spéciales de votre part. Si tel est votre problème, je vous renverrai au récent article de blog d'Andreas Hausladen sur le sujet.

Si vous perdez 115 instances de cette classe, c'est cette classe qui subit une fuite. La mémoire occupée par cette classe, pas la mémoire occupée par les choses auxquelles elle fait référence, est en train de fuir. Quelque part, vous ne libérez pas 115 instances de TCwcBasicAdapter .

En outre, les propriétés ne stockent pas de données, peu importe leur interface ou un autre type. Seuls les champs occupent de la mémoire (avec un peu d’espace caché alloué par le compilateur au nom de la classe).

Donc, oui, vous êtes en train d'aboyer le mauvais arbre. Votre fuite de mémoire est ailleurs. Lorsque FastMM vous indique que vous avez une fuite de mémoire, cela ne vous indique-t-il pas également où chaque instance ayant fait l'objet d'une fuite a été allouée. Il a cette capacité; vous devrez peut-être ajuster certains symboles de compilation conditionnelle pour activer cette fonctionnalité.

Toutefois, ce ne sont pas seulement les instances de cette classe qui fuient. FastMM devrait également signaler d'autres problèmes, tels que des instances de la classe ou des classes qui implémentent l'interface.

En fonction de la fonction que vous avez ajoutée, j'ai commencé à soupçonner que c'est vraiment TCwcCDSAdapterNavBase qui fuyait, en raison peut-être de la manière atypique que vous utilisez pour le créer. Le gestionnaire d'exceptions de GetAdapterNav est-il exécuté? J'en doute; TObject.GetInterface ne déclenche jamais explicitement une exception. Si l'objet ne prend pas en charge l'interface, il retourne False . Tout ce que le gestionnaire d'exceptions pourrait attraper est des choses comme la violation d'accès et les opérations illégales, que vous ne devriez vraiment pas attraper là-bas de toute façon.

Vous pouvez implémenter cette fonction plus directement comme ceci:

if Assigned(FDataSet) then
  Result := TCwcCDSAdapterNavBase.Create(...);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top