[Erledigt] Heaptrc Problem mit Freigabe

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

[Erledigt] Heaptrc Problem mit Freigabe

Beitrag von MacWomble »

Ich habe eine Routine im Programm, welche Speicherbereiche belegt aber nicht wieder frei gibt und komme nicht auf die Ursache:

Code: Alles auswählen

procedure TdtmBasis.acDokument_ComposeExecute(Sender: TObject);
var
  VorlageDatei, ZielDatei, DateiName, TempDir, RelDir: string;
  AUnZipper: TUnZipper;
  AZipper: TZipper;
  ZEntries: TZipFileEntries;
  ZipFileList: TStringList;
  i: integer;
begin
  OpenDialog.InitialDir := GetIniFile('Pfade', 'Autovorlage', '');
  OpenDialog.Filter := 'Vorlage|*.odt';
  if OpenDialog.Execute then
  begin
    VorlageDatei := OpenDialog.FileName;
    DateiName := ExtractFileNameWithoutExt(ExtractFileName(VorlageDatei));
    if InputQuery('Dokumentenname', 'Bezeichnung für das Dokument eingeben', DateiName) = False then
      exit
    else
    begin
      //TODO: Dokumenteneintrag erstellen
 
      // ZielDatei mit Pfad
      ZielDatei := 'Test.odt';
 
 
      //Dokument nach Temp entpacken
      TempDir := '/tmp/CTR_Zipper';
      relDir := TempDir;
      DeleteDirectory(TempDir, False);
      AUnZipper := TUnZipper.Create;
      try
        AUnZipper.FileName := VorlageDatei;
        AUnZipper.OutputPath := TempDir;
        AUnZipper.Examine;
        AUnZipper.UnZipAllFiles;
      finally
        AUnZipper.Free;
      end;
      //Temp-Dokument Platzhalter ersetzen
      //ReplaceInODTFile(TempDir + PathDelim + '/content.xml');
      //ReplaceInODTFile(TempDir + PathDelim + '/styles.xml');
      //Temp-Dokument nach Ziel-Dokument packen
      AZipper := TZipper.Create;
      try
        AZipper.Filename := ZielDatei;
        AZipper.Clear;
        ZEntries := TZipFileEntries.Create(TZipFileEntry);
        if DirPathExists(TempDir) then
        begin
          //szPathEntry := TempDir;
          ZipFileList := TStringList.Create;
          try
            ZipFileList := FindAllFiles(RelDir);
            for i := 0 to ZipFileList.Count - 1 do
              ZEntries.AddFileEntry(ZipFileList[i],
                CreateRelativePath(ZipFileList[i], RelDir));
          finally
            ZipFileList.Free;
          end;
        end;
        if (ZEntries.Count > 0) then
          AZipper.ZipFiles(ZEntries);
        DeleteDirectory(TempDir, False);
      finally
        FreeAndNil(ZEntries);
        AZipper.Free;
      end;
      //ZielDokument zum Bearbeiten öffnen
      OpenDocument(ZielDatei);
    end;
  end;
end;                                 


Code: Alles auswählen

Heap dump by heaptrc unit
579598 memory blocks allocated : 145037001/146550296
579597 memory blocks freed     : 145036849/146550144
1 unfreed memory blocks : 152
True heap size : 3571712
True free heap : 3571392
Should be : 3571432
Call trace for block $00007F74AE574C00 size 152
  $00000000004CB7EC
  $00000000007051FF
  $00000000004CB4D2
  $00000000005C97F9
  $00000000005C9FFB
  $00000000005C96E2
  $0000000000432136
  $000000000055C5DC
 


Hat jemand eine Idee? Was habe ich vergessen?
Zuletzt geändert von MacWomble am Mi 22. Nov 2017, 13:32, insgesamt 1-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Heaptrc Problem mit Freigabe

Beitrag von af0815 »

möglicher Hint: IMPORTANT NOTE: The function "FindAllFiles" creates the stringlist internally. This may look very convenient at first sight, but it is very easy to create memory leaks that way:

Siehe http://wiki.freepascal.org/FindAllFiles

Ich weis jetzt anhand deines Codes nicht unbedingt welche Version genommen wird. Procedure oder Function (mit verworfenen Ergebnis).

Andreas
Zuletzt geändert von af0815 am Mi 22. Nov 2017, 13:26, insgesamt 1-mal geändert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Heaptrc Problem mit Freigabe

Beitrag von wp_xyz »

Mein Liebling FindAllFiles hat wieder zugeschlagen.,,

Wenn du FindAllFiles als Funktion verwendest, musst du wissen, dass diese eine Stringliste erzeugt, der vorige Aufruf von TStringList.Create ist somit unnötig und verursacht das Speicherleck. Oder du nimmst die Prozedur FindAllFiles, der man als 1.Parameter die StringList übergeben kann.

Code: Alles auswählen

// Variante 1
          ZipFileList := FindAllFiles(RelDir);
          try
            for i := 0 to ZipFileList.Count - 1 do
              ZEntries.AddFileEntry(ZipFileList[i],
                CreateRelativePath(ZipFileList[i], RelDir));
          finally
            ZipFileList.Free;
          end;
 
// oder Variante 2:
          ZipFileList := TStringList.Create;
          try
            FindAllFiles(ZipFileList, RelDir);
            for i := 0 to ZipFileList.Count - 1 do
              ZEntries.AddFileEntry(ZipFileList[i],
                CreateRelativePath(ZipFileList[i], RelDir));
          finally
            ZipFileList.Free;
          end;

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Heaptrc Problem mit Freigabe

Beitrag von MacWomble »

Danke, das war die Ursache ! (TStringList.Create)

Böööse Falle!

Zwei Volltreffer ;-)
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Antworten