Einzelnen Beitrag anzeigen

Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
827 Beiträge
 
Delphi 10.4 Sydney
 
#1

Speicherleaks TMemoryStream in einem Objekt

  Alt 22. Dez 2023, 16:46
Hallo Zusammen,
ich habe meine Client-Server App massiv umgebaut und dabei soviele Speicherleaks geschaffen, dass die Anwendung wegen überfülltem Speicher nach 1-2 Stunden abstürzt.
Allerdings finde ich den Fehler nicht.
Ich versuche mich gerade in FastMM4 einzuarbeiten.

Aber mal eine grundsätzliche Frage:
Werden TMemoryStreams, die ich in einem Objekt definiere, freigegeben, wenn ich das Objekt freigebe?

Beispiel:
Definition
Delphi-Quellcode:
Type
   TMxSQL = class
      fColsSetMain: TCols;
      fRowsSetMain: TRows;
      fStreamSetMain: TMemoryStream;
      fColsSetBSC: TCols;
      fRowsSetBSC: TRows;
      fStreamSetBSC: TMemoryStream;
   private
      { Private-Deklarationen }
   public
      { Public-Deklarationen }
      property ColsSetMain: TCols read fColsSetMain write fColsSetMain;
      property RowsSetMain: TRows read fRowsSetMain write fRowsSetMain;
      property ColsSetBSC: TCols read fColsSetBSC write fColsSetBSC;
      property RowsSetBSC: TRows read fRowsSetBSC write fRowsSetBSC;
      property StreamSetMain: TMemoryStream read fStreamSetMain write fStreamSetMain;
      property StreamSetBSC: TMemoryStream read fStreamSetBSC write fStreamSetBSC;
      constructor Create(GetSets: boolean = true);
Aufruf aus der Form
Delphi-Quellcode:
procedure TFrm_Main_BSC.FormShow(Sender: TObject);
var I: integer;
      SpecialStart: boolean;
      MxSQL: TMxSQL;
begin
   Try
      MxSQL:= TMxSQL.Create;
      Try
       ...
      Finally
         MxSQL.Free;
      End;
Der Constructor
Delphi-Quellcode:
constructor TMxSQL.Create(GetSets: boolean);
begin
   if GetSets then begin
      fStreamSetMain:= TMemoryStream.Create;
      GetSettings('hlp_properties');
      fStreamSetBSC:= TMemoryStream.Create;
      GetSettings('hlp_properties_bsc');
   end;
end;
Die Datenbank-Abfrage:
Delphi-Quellcode:
procedure TMxSQL.GetSettings(Tabelle: string);
var LClient: TxDataClient;
      LService: IDBService;
      Logic: TLogic;
begin
   LClient := TXDataClient.Create;
   Logic:= TLogic.Create;
   Try
      LClient.Uri:= DB_Unit.xData_Connect.URL;
      LService:= LClient.Service<IDBService>;
      if Tabelle = 'hlp_properties_bscthen begin
         fStreamSetBSC:=LService.Properties_BSC_Select as TMemoryStream;
         fStreamSetBSC.Position:=0;
         Logic.StreamToRows(fStreamSetBSC, fColsSetBSC, fRowsSetBSC);
      end
      else if Tabelle = 'hlp_propertiesthen begin
         fStreamSetMain:=LService.Properties_Select as TMemoryStream;
         fStreamSetMain.Position:= 0;
         Logic.StreamToRows(fStreamSetMain, fColsSetMain, fRowsSetMain);
      end;
   Finally
      LClient.Free;
      Logic.Free;
   end;
end;
Hierbei passiert irgendwo neben vielen anderen Stellen eine Speicherleak.

Das ist die Zusammenfassung aus dem Report von FastMM4:
Zitat:
--------------------------------2023/12/22 15:07:18--------------------------------
This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):

21 - 36 bytes: System.Classes.TBytesStream x 9, System.Classes.TMemoryStream x 20
1509 - 1668 bytes: Unknown x 1

The sizes of leaked medium and large blocks are (excluding expected leaks registered by pointer): 37796, 8356, 37796, 37796, 41124, 7844, 8356, 7332
Müsste ich fStreamSetMain und fStreamSetBSC separat vor MxSQL.Free freigeben oder werden die mit freigegeben?

Vielen Dank
Patrick
Patrick
  Mit Zitat antworten Zitat