![]() |
Memory leak durch funktion readln
Hallo zusammen,
ich hab mich grade erst hier angemeldet, und das ist auch das erste mal dass ich mich in einem delphi forum anmelde, also wenn ich mich nicht an irgendwelche reglen halte, die ihr hier einhaltet, dann nur weil ich es nicht besser weiß, also schonmal sorry im voruas:) Hier mein Problem: Ich führe eine Projektzusammenführung durch, hat alles ganz gut geklappt, bis ich auf ein erhebliches memory leak gestoßen bin, das mit der fehlermeldung out of memory geendet hat, mit Hilfe von FastMM konnte ich einen Leck finden, sodass mein Code jetzt läuft ohne abzuschmieren, aber der Arbeitsspeicher wird dennoch stetig mit zunehmender Zeit gekillt. Dann hab ich weiter gesucht und iwo gelesen, dass FastMM keine leaks bezüglich externer Datein findet, dann hab ich mir genauer angeguckt ob das bei mir zutrifft, und es hat gepasst. Ich lese eine Datei mit readln ein und schreibe später die umgewandelten Daten in eine andere Datei. Ich hab den Code mal auf das Grundproblem reduziert:
Delphi-Quellcode:
Ich beobachte das gnaze mit dem Ressource Monitor von Windows.
procedure sterb_schleife;
var quell_dat, grossdatei: text; begin assign(grossdatei, pfad_aus + gesell + 'big.txt'); rewrite(grossdatei); quell_dat_name := 'test.TXT'; assign(quell_dat, pfad_ein + gesell + '\' + quell_dat_name); reset(quell_dat); while not eof(quell_dat){zaehler_gesamt<1200000} do begin readln(quell_dat, zeile); Writeln(grossdatei, zeile); //////////////////////////////// inc(zaehler_gesamt); if ((zaehler_gesamt mod 1000) = 0) then dsnr.strings[1] := inttostr(zaehler_gesamt); end; flush(quell_dat); close(quell_dat); flush(grossdatei); close(grossdatei); end; Das readln sollte doch eigentlich nur eine Zeile einlesen, aber scheinbar ließt es eine zeile und hält sie im speicher und dann die nächste, usw., da kann ich ja direkt mit der tstringlist und loadfromfile arbeiten, das Problem bei der Sache ist, dass meine text dateien bis zu 2 gb groß sein können.. Ich und sogar mein Chef wir sind ratlos. Habtz ihr eine alternative Idee, oder seht ihr den groben Denkfehler? Ich habe schon gelesen, dass man die Output datei hin und wieder schliießen und neu öffnen soll, hat aber auch nix gebracht. Und jetzt kommt der Brüller, in meinen großen Programm tritt der Fehler mal auf und mal nicht, ich kann ihn nicht wirklich reproduzieren... Es wäre echt mehr als coolm, wenn ihr mir iwie weiter helfen könntet, denn sosnt sthet mein Projekt leider vor dem aus:(( Ich überlege sogar das Projekt in Java umzuschreiben, weil ich eigentlich ein großer Fan vom Garbage collector bin, aber performancemäßig rät mir mein chef davon ab... DAaaaaaaaanke und viele Größe Daniel |
AW: Memory leak durch funktion readln
Bei so großen Dateien würde ich direkt
![]() |
AW: Memory leak durch funktion readln
Wieso ist "Zeile" nicht lokal deklatiert?
Und ja, Text-Reads gehen immer über einen Puffer. * dort wird der Inhalt stückchenweise reinkopiert * da drin wird dann nach dem nächsten Zeilenumbruch gesucht (bzw nach dem Ende der für die Leseoperation ... z.B. das Ende der Zahl für
Delphi-Quellcode:
)
Read(Datei, MyInteger)
* und dann wird dort das zu Lesende rauskopiert, nachdem man weiß, bis wohin gelesen werden muß PS: Auch das Writeln geht erstmal in diesen Cache.
Delphi-Quellcode:
PTextBuf = ^TTextBuf;
TTextBuf = array[0..127] of AnsiChar; TTextRec = packed record Handle: THandle; Mode: Word; ... Name: array[0..259] of WideChar; Buffer: TTextBuf; // der Standardpuffer direkt in der "TEXT"-Variable end; |
AW: Memory leak durch funktion readln
Was wäre dabei der Vorteil?
Byteweise einlesen heißt, aber auch, dass ich nicht automatisch ganze zeilen einlesen kann oder doch? |
AW: Memory leak durch funktion readln
Zitat:
Flush auf die Quelle? Also ich denke nicht das ein ReadLn/Writeln ein MemoryLeak produziert. Bist Du sicher, dass Du uns "genug" Sourcecode gepostet hast? Mavarik |
AW: Memory leak durch funktion readln
Code der zumindest compiliert wäre sicher extrem hilfreich.
|
AW: Memory leak durch funktion readln
byteweises Einlesen ist suboptimal (langsamer und resoursenlastiger)
Text ist wie "file of string" oder "file of char" und gibt es schon seit Turbo Pascal |
AW: Memory leak durch funktion readln
Zitat:
Delphi-Quellcode:
{$O-}
unit sterb; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, deklara, plausi, struktur, Zaehler; procedure sterb_schleife; implementation procedure sterb_schleife; var autodatei, quell_dat, plausidatei, mrdatei, toddatei, hilfdatei, grossdatei: text; kette, plausikette: string; fehler, i, j, zaehler, plausibele, unplausibel, position: integer; begin meldung.add('Gesellschaftskennzeichen: ' + gesell); {autodatei = Steuerdatei für ausgewählte Gesellschaft, enthält Liste der gelieferten Dateien} assign(autodatei, pfad_ein + gesell + 'inp.txt'); reset(autodatei); //########################## //VU Ordner selbst anlegen //############################# if not DirectoryExists(pfad_aus+gesell) then ForceDirectories(pfad_aus+gesell); //########################## //alle dateipfade geändert, +gesell+'\' + hinzugefügt //############################# {mrdatei = Datei für Münchener Rück. Wird aber scheinbar nicht mehr gebraucht} assign(mrdatei, pfad_aus +gesell+'\' + gesell + 'mr.txt'); rewrite(mrdatei); {toddatei: Wenn satz.zustand[1] = 'T' dann Datensatz rausschreiben.} assign(toddatei, pfad_aus +gesell+'\' + gesell + 'tod.txt'); rewrite(toddatei); {grossdatei: Immer Datensatz rausschreiben.} assign(grossdatei, pfad_aus +gesell+'\' + gesell + 'big.txt'); rewrite(grossdatei); assign(hilfdatei, pfad_aus +gesell+'\' +gesell + 'hilf.txt'); rewrite(hilfdatei); meldung.add('Initialisieren der Variablen'); zaehler_gesamt := 0; zaehler_nicht_verarbeitet := 0; for i := 1 to mwcount do for j := 1 to nwcount do wcount[i, j] := 0; struktur_insp(false); //Strukturtabellen initialisieren meldung.add(' Lesen der Versicherungsdaten.'); readln(autodatei, kette); while kette <> 'ende' do begin quell_dat_name := kette; {quelldat= ausgewählte gelieferte Datei der ausgewählten Gesellschaft} meldung.add('***' + kette + '***'); assign(quell_dat, pfad_ein + gesell + '\' + quell_dat_name); reset(quell_dat); position := length(kette); plausikette := kette; plausikette[position - 3] := kette[position - 2]; plausikette[position - 2] := kette[position - 1]; plausikette[position - 1] := kette[position]; plausikette[position] := '.'; assign(plausidatei, pfad_aus + gesell + '\plausi_' + plausikette + 'txt'); rewrite(plausidatei); //Für Datei spezifiziertes Meldejahr in datmelde_jahr einlesen: readln(autodatei, kette); val(kette, datmelde_jahr, fehler); //Entscheiden, ob neues oder altes Datenformat verwendet wird // alt = Datenformat bis 2004 ohne neue Felder // uebergang = Datenformat bis 2004, neue Felder am Ende angehängt // neu = Ab 2005 vorgeschlagener einheitlicher Datensatz für alle Pools readln(autodatei, kette); if kette = 'neu' then datenformat := 2 else if kette = 'uebergang' then datenformat := 1 else if kette = 'alt' then datenformat := 0 else messagedlg('Keine gültige Spezifikation des Datenformats in der Steuerdatei!', mtinformation, [mbOk], 0); zaehler := 0; plausibele := 0; unplausibel := 0; //in Daten von Quelle-Versicherung erste Zeile =Überschrift überlesen if gesell = 'QU' then readln(quell_dat, zeile); {Datensätze in quell_dat einlesen und auswerten} while not eof(quell_dat) do begin umfehler := false; sterb_fehler := false; istrente := true; ///////////////////////// readln(quell_dat, zeile); if ioresult <> 0 then begin messagedlg('Fehler beim Lesen der Datei!', mtError, [mbOk], 0); break; end; //BG2010: Wenn Zeile mit Hochkomma beginnt, dann Einlesevorgang abbrechen... if zeile[0] = '''' then break; inc(zaehler); va2i := 1; if gesell = 'QU' then umwandel_quelle(datenformat) {else if gesell = 'MA' then umwandel_mannheimer} //else if gesell = 'MR' then umwandel_mr //////////////////////////// else umwandel(datenformat); //////////////////////////// //if satz.gesellschaft = 'EU' then writeln(mrdatei, zeile); if umfehler then begin writeln(plausidatei, zaehler, ';100;Umwandelfehler'); inc(unplausibel); end; if (not umfehler) and istrente then begin if satz.vers_art[2] = 'L' then va2i := 2; plausibel(plausidatei, zaehler); if sterb_fehler then inc(unplausibel); if not sterb_fehler then begin inc(plausibele); codieren(zaehler); //Werte in Strukturtabellenindizes übersetzen struktur_zaehlen(zaehler); //Strukturtabellen belegen //val(copy(satz.geb_datum, 1, 4), gebjahr, fehler); {if (code.geschlecht = 2) and ((gebjahr = 1936) or (gebjahr = 1937)) then} //////////////////////////////// sterb_zaehlen(hilfdatei, zaehler, steuerung_ausgabe); //Sterblichkeits-Zaehlertabelle belegen //////////////////////////////// schreibe_grossdatei(grossdatei); //////////////////////////////// end; if abbruch then exit; if umfehler or sterb_fehler then inc(zaehler_nicht_verarbeitet); inc(zaehler_gesamt); str(zaehler_gesamt, kette); if ((zaehler_gesamt mod 1000) = 0) then dsnr.strings[1] := kette; end; end; flush(quell_dat); close(quell_dat); writeln(plausidatei, zaehler, ';Datensätze'); writeln(plausidatei, unplausibel, '; unplausible Datensätze'); writeln(plausidatei, plausibele, '; plausible Datensätze'); flush(plausidatei); close(plausidatei); //close(mrdatei); readln(autodatei, kette); end; {*kette='ende' in autodatei*} meldung.add('Speichern der Struktur-Tabellen'); struktur_insp(true); //Strukturtabellen speichern flush(mrdatei); close(mrdatei); flush(toddatei); close(toddatei); flush(grossdatei); close(grossdatei); flush(hilfdatei); close(hilfdatei); meldung.add(' '); str(zaehler_gesamt, kette); meldung.add('Datensätze gesamt: ' + kette); str(zaehler_nicht_verarbeitet, kette); meldung.add(' davon nicht verarbeitet: ' + kette); str(plausibele, kette); meldung.add('Datensätze plausibel: ' + kette); meldung.add(' '); zaehler_ausgabe(wcount); end; end. |
AW: Memory leak durch funktion readln
Wann wird die Stringliste meldung geleert?
|
AW: Memory leak durch funktion readln
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz