Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Speicherleck bei Verwendung von TInterfacedPersistent? (https://www.delphipraxis.net/101853-speicherleck-bei-verwendung-von-tinterfacedpersistent.html)

squetk 19. Okt 2007 01:52


Speicherleck bei Verwendung von TInterfacedPersistent?
 
Hallo,

leite ich Klassen von TInterfacedPersistent ab, meldet mir FastMM, dass diese Klasse ein Speicherleck verursacht.
Folgendes Beispiel:
Delphi-Quellcode:
unit ClassesSB;

interface

uses SysUtils, Classes;

type
  ISBParam = interface(IInterface)
    ['{3A2C91E1-9935-436B-BCCE-489F0615F5D1}']
    function GetValue(const sParamFieldName : string; const iParamType : integer) : string;
  end;

  TSBParamClass = class of TSBParam;

  TSBParam = class(TInterfacedPersistent, ISBParam)
  //TSBParam = class(TInterfacedObject, ISBParam)
  private
  public
    function GetValue(const sParamFieldName : string; const iParamType : integer) : string; virtual;
  end;

  TSBParamTest = class(TSBParam)
  private
  public
    function GetValue(const sParamFieldName : string; const iParamType : integer) : string; override;
  end;

implementation

{ TSBParam }

function TSBParam.GetValue(const sParamFieldName: string;
  const iParamType: integer): string;
begin
  Result := '';
end;

{ TSBParamTest }

function TSBParamTest.GetValue(const sParamFieldName: string;
  const iParamType: integer): string;
begin
  Result := Format('Param=%s Type=%d', [sParamFieldName, iParamType]);
end;

initialization

  RegisterClasses([TSBParamTest]);


end.
Und so wird es verwendet:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var sbParam : ISBParam;
begin
  sbParam := TSBParamClass(FindClass('TSBParamTest')).Create;
  //sbParam := TSBParamTest.Create;
  ShowMessage(sbParam.GetValue('FieldName', 1));
end;
Nutze ich TInterfacedObject als Basisklasse (Kommentare), ist FastMM zufrieden. Allerdings hatte ich vor, die Klassen aus dem Namen als Text zu erzeugen (die Klassennamen sind extern gespeichert), und FindClass arbeitet nur mit Derivaten von TPersistentClass.

Sicher wäre es ein Wordaround, das FindClass mit einer eigenen Listenklasse nachzubilden - aber den Aufwand würde ich mir gern sparen. Ausserdem interessiert es mich, ob wirklich ein Speicherleck entsteht oder FastMM hier eine Falschmeldung produziert.

Dax 19. Okt 2007 02:33

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Ich kann es nicht beweisen, aber ich vermute mal ins blaue, dass TInterfacedPersistent die Referenzzählung aushebelt. Produziert folgender Code ein Leck?
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var sbParam : ISBParam; temp: TSBParamClass;
begin
  temp := TSBParamClass(FindClass('TSBParamTest')).Create;
  sbParam := temp;
  //sbParam := TSBParamTest.Create;
  ShowMessage(sbParam.GetValue('FieldName', 1));
  temp.Free;
end;

squetk 19. Okt 2007 02:39

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Es gibt beim temp.Free eine Schutzverletzung - ist das eventuell ein Indiz dafür, dass FastMM eine Speicherleck-Falschmeldung produziert?

Dax 19. Okt 2007 02:43

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Args! Ich sollte nicht so spät noch Fragen beantworten... Das sollte natürlich TSBParam in der Variablendeklaration heißen, nicht TSBParamClass *schämt sich in grund und boden*

squetk 19. Okt 2007 02:49

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Da hat mich schon der Compiler drauf aufmerksam gemacht, das war also nicht die Ursache für die Schutzverletzung, die Variablendeklaration hatte ich berichtigt.
Zitat:

Ich sollte nicht so spät noch Fragen beantworten...
Spät? Ich finds eher früh :wink:

Dax 19. Okt 2007 02:53

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Zitat:

Zitat von squetk
Spät? Ich finds eher früh :wink:

Sag das mir, so ich seit Wochen nich mehr richtig und seit gestern garnich mehr schlafen kann.. Aber zum Thema: wenn es selbst bei einer richtigen Deklaration der Variablen eine Schutzverletzung gibt, würde ich diese Konstellation zum einen mit einem anderen Memorymanager ausprobieren (sollte das selbe Ergebnis liefern) und in einem anderen Test die Interfaces weglassen. Wie dein Leck zustande kommt, entzieht sich meiner Erkenntnis.. Und die AV deutet auf einen schweren Fehler in einem anderen Programmteil hin. Hast du eventuell Destroy überschrieben und inherited nicht drin? Oder noch schlimmer, Free redeklariert?

squetk 19. Okt 2007 03:01

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Nein - solch schlimme Sachen habe ich nicht gemacht. Alles was ich gecodet habe, ist im ersten Beitrag zu sehen - ganz harmlos.
Sobald ich statt TInterfacedPersistent TInterfacedObject verwende, habe ich ja das gewünschte Ergebnis. Dann kann ich aber FindClass nicht nutzen.
Ich habe mal in den Sourcen nachgeschaut (Classes.pas), dort werden die Methoden _AddRef etc. bei TInterfacedPersistent anders implementiert als bei TInterfacedObject. Merkwürdig.

Dax 19. Okt 2007 03:03

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Also wie vermutet, die Referenzzählung wird ausgehebelt.. Was in dem Fall das beste Vorgehen ist kann ich nicht sagen, aber wenn du auf die Referenzzählung angewiesen bist, könntest du versuchsweise die Implementation aus TInterfacedObject in deine Basisklasse packen (und eventuell dort behalten).

squetk 19. Okt 2007 03:07

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Also eine Klasse von TInterfacedPersistent ableiten und dann das Referenz-Handling von TInterfacedPersistent mit der Implementation von TInterfacedObject überschreiben?
Klingt nicht übel.
Mal schaun ob das klappt.

squetk 19. Okt 2007 05:56

Re: Speicherleck bei Verwendung von TInterfacedPersistent?
 
Komisch: Ich habe eine Klasse TPatchInterfacedPersistent von TInterfacedPersistent abgeleitet und die _AddRef und _Release-Methoden und alle weiteren mit der Implementation von TInterfacedObject überschrieben und die das Interface implementierenden Klassen davon abgeleitet - trotzdem kommt es zum Speicherleck.

Da scheint ein anderes Problem in TInterfacedPersistent verborgen zu sein. :gruebel:

Ich werde wohl das Handtuch schmeissen und eine eigene Listenklasse coden, die mir die FindClass-Funktionalität liefert. Dann können meine implementierenden Klassen von TInterfacedObject abgeleitet sein und es herrscht eitel Sonnenschein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:26 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz