[Erledigt] Heaptrc Problem mit Freigabe

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

[Erledigt] Heaptrc Problem mit Freigabe

Beitragvon MacWomble » 22. Nov 2017, 13:04 [Erledigt] Heaptrc Problem mit Freigabe

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 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.
MacWomble
 
Beiträge: 419
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 18.3 Cinnamon / CodeTyphon Generation V Plan 6.00 (FPC 3.1.1) | 
CPU-Target: 32/64 Nit
Nach oben

Beitragvon af0815 » 22. Nov 2017, 13:23 Re: Heaptrc Problem mit Freigabe

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 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).
af0815
 
Beiträge: 3291
Registriert: 7. Jan 2007, 10:20
Wohnort: Niederösterreich
OS, Lazarus, FPC: Win7/Linux (L stable FPC stable) per fpcup | 
CPU-Target: 32Bit (64Bit)
Nach oben

Beitragvon wp_xyz » 22. Nov 2017, 13:26 Re: Heaptrc Problem mit Freigabe

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;
wp_xyz
 
Beiträge: 2362
Registriert: 8. Apr 2011, 08:01

Beitragvon MacWomble » 22. Nov 2017, 13:31 Re: Heaptrc Problem mit Freigabe

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.
MacWomble
 
Beiträge: 419
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 18.3 Cinnamon / CodeTyphon Generation V Plan 6.00 (FPC 3.1.1) | 
CPU-Target: 32/64 Nit
Nach oben

• Themenende •

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

porpoises-institution
accuracy-worried