Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Memory leak durch funktion readln (https://www.delphipraxis.net/184250-memory-leak-durch-funktion-readln.html)

danieldelphi 12. Mär 2015 10:20

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:
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;
Ich beobachte das gnaze mit dem Ressource Monitor von Windows.
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

Zacherl 12. Mär 2015 10:24

AW: Memory leak durch funktion readln
 
Bei so großen Dateien würde ich direkt Delphi-Referenz durchsuchenTFileStream verwenden.

himitsu 12. Mär 2015 10:27

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;

danieldelphi 12. Mär 2015 10:31

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?

Mavarik 12. Mär 2015 10:32

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von danieldelphi (Beitrag 1293132)
Delphi-Quellcode:
procedure sterb_schleife;
var
  quell_dat, grossdatei: text; // ??????? C++

    flush(quell_dat); // ??????

end;

hmm Welche Delphi Version soll das den sein?
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

Der schöne Günther 12. Mär 2015 10:33

AW: Memory leak durch funktion readln
 
Code der zumindest compiliert wäre sicher extrem hilfreich.

himitsu 12. Mär 2015 10:33

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

danieldelphi 12. Mär 2015 10:36

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Mavarik (Beitrag 1293139)
Zitat:

Zitat von danieldelphi (Beitrag 1293132)
Delphi-Quellcode:
procedure sterb_schleife;
var
  quell_dat, grossdatei: text; // ??????? C++

    flush(quell_dat); // ??????

end;

hmm Welche Delphi Version soll das den sein?
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

das ist delphi 6. ich bin eig sicher dass ich euch genug gepostet habe, ich kann aber gern noch mehr raus hauen, also hier das problem im großen
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.

Union 12. Mär 2015 10:38

AW: Memory leak durch funktion readln
 
Wann wird die Stringliste meldung geleert?

danieldelphi 12. Mär 2015 10:39

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1293140)
Code der zumindest compiliert wäre sicher extrem hilfreich.

ich verstehe nicht ganz? wie meinst du das?

danieldelphi 12. Mär 2015 10:40

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Union (Beitrag 1293143)
Wann wird die Stringliste meldung geleert?

die wird gar nicht geleert, bzw beim beenden des programms, aber da kommen nur ein paar zeilen rein, die auf dem form angezeigt werden

Mavarik 12. Mär 2015 10:40

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von danieldelphi (Beitrag 1293138)
Was wäre dabei der Vorteil?
Byteweise einlesen heißt, aber auch, dass ich nicht automatisch ganze zeilen einlesen kann oder doch?

Performance...

Gerade bei 2GB große Files...

Wobei Du natürlich NICHT "Byteweise" lesen solltest sondern:

Sondern eher eine Lesepuffer von 16MB oder größer nehmen...

Und dann die 16MB direkt in einem Rutsch mit einen Blockread lesen...

In Memory dann mit einem Zeiger durchlaufen und entsprechend per Blockwrite wegschreiben...
NIX ist schneller auch nicht der FileStream... :stupid:
Der nutz nämlich genau die gleichen Routinen intern wie der Blockread... Nur mit mehr Overhead!

Mavarik

danieldelphi 12. Mär 2015 10:43

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Mavarik (Beitrag 1293146)
Zitat:

Zitat von danieldelphi (Beitrag 1293138)
Was wäre dabei der Vorteil?
Byteweise einlesen heißt, aber auch, dass ich nicht automatisch ganze zeilen einlesen kann oder doch?

Performance...

Gerade bei 2GB große Files...

Wobei Du natürlich NICHT "Byteweise" lesen solltest sondern:

Sondern eher eine Lesepuffer von 16MB oder größer nehmen...

Und dann die 16MB direkt in einem Rutsch mit einen Blockread lesen...

In Memory dann mit einem Zeiger durchlaufen und entsprechend per Blockwrite wegschreiben...
NIX ist schneller auch nicht der FileStream... :stupid:
Der nutz nämlich genau die gleichen Routinen intern wie der Blockread... Nur mit mehr Overhead!

Mavarik

okay also du sagst 16 mb blockweise einlesen und damit dann weiter arbeiten?
kann man da denn noch gut nahc zeilen unterscheiden? ich gehe mal davon aus, dass es schwierig sein wird 16 mb auszulesen ohne dabei eine zeile zu zerschneiden, denn meine zeilen stellen zusammenhängede datensätze dar:/

mm1256 12. Mär 2015 10:44

AW: Memory leak durch funktion readln
 
Speichermäßig ist das doch am einfachsten mit zeilenweiser String-Bearbeitung, oder?

Delphi-Quellcode:
procedure Die_Schleife_Stirbt_Nicht(Von,Nach: string);
var
  T1, T2: TextFile;
  Zeile: string;
begin
  AssignFile(T1,Von); // bzw. Assign(T1,Von); in D6
  Reset(t1);
  AssignFile(T2,Nach);
  Rewrite(T2);
  while not EOF(T1) do begin
    ReadLn(T1,Zeile);
    // Zeileninhalt bearbeiten
    WriteLn(T2,Zeile);
  end;
  CloseFile(T1); // bzw. Close(T1) in D6
  CloseFile(T2);
end;

danieldelphi 12. Mär 2015 10:47

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von mm1256 (Beitrag 1293148)
Speichermäßig ist das doch am einfachsten mit zeilenweiser String-Bearbeitung, oder?

Delphi-Quellcode:
procedure Die_Schleife_Stirbt_Nicht(Von,Nach: string);
var
  T1, T2: TextFile;
  Zeile: string;
begin
  AssignFile(T1,Von); // bzw. Assign(T1,Von); in D6
  Reset(t1);
  AssignFile(T2,Nach);
  Rewrite(T2);
  while not EOF(T1) do begin
    ReadLn(T1,Zeile);
    // Zeileninhalt bearbeiten
    WriteLn(T2,Zeile);
  end;
  CloseFile(T1); // bzw. Close(T1) in D6
  CloseFile(T2);
end;

gebnau das ist ja der ausgangspunkt, so ist am ende der arbeitsspeicher mit der einzulesesnden datei gefüllt.

Mavarik 12. Mär 2015 10:47

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von danieldelphi (Beitrag 1293142)
das ist delphi 6.

hmm cool

Unter Delphi 6 ist ein String immer ein Shortstring... Oder verwechsele ich da gerade etwas? Ist zu lange her...

Bist Du sicher, das Deine Zeilen in den Textdateien kürzer als 255 Zeichen sind?

Mavarik

DeddyH 12. Mär 2015 10:49

AW: Memory leak durch funktion readln
 
Du bist anscheinend bei Delphi 1 stehengeblieben, in Delphi 2 bis 2007 ist ein String ein AnsiString.

danieldelphi 12. Mär 2015 10:49

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Mavarik (Beitrag 1293150)
Zitat:

Zitat von danieldelphi (Beitrag 1293142)
das ist delphi 6.

hmm cool

Unter Delphi 6 ist ein String immer ein Shortstring... Oder verwechsele ich da gerade etwas? Ist zu lange her...

Bist Du sicher, das Deine Zeilen in den Textdateien kürzer als 255 Zeichen sind?

Mavarik

ich bin mir nicht sicher, bzw ich weiß, dass die zeieln teilweise über 300 zeichen haben, aber zeile ist bei mir auch ein char array mit 500 zeichen den ich dann in der procedure in einen string umwandel, siehst du da ein problem dass ich nicht sehe?

Mavarik 12. Mär 2015 10:50

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von deddyh (Beitrag 1293152)
du bist anscheinend bei delphi 1 stehengeblieben, in delphi 2 bis 2007 ist ein string ein ansistring.

ok ok...

mm1256 12. Mär 2015 10:53

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von danieldelphi (Beitrag 1293149)
gebnau das ist ja der ausgangspunkt, so ist am ende der arbeitsspeicher mit der einzulesesnden datei gefüllt.

Aber genauso mach ich das schon jahrelang mit großen Textdateien ohne Probleme. Schau dir deinen Code genauer an, da musst du ein Problem haben.

Was soll z.B. das...wenn angenommen "Zeile" eine Stringvariable ist:

Delphi-Quellcode:
//BG2010: Wenn Zeile mit Hochkomma beginnt, dann Einlesevorgang abbrechen...
      if zeile[0] = '''' then break;

Mavarik 12. Mär 2015 10:55

AW: Memory leak durch funktion readln
 
Hast Du das mal mit {$R+,O+} compiliert?

baumina 12. Mär 2015 10:57

AW: Memory leak durch funktion readln
 
Vielleicht hilft ja auch das hier weiter SJ MMF File Reader - Schneller Textdatei Reader

danieldelphi 12. Mär 2015 10:59

AW: Memory leak durch funktion readln
 
Liste der Anhänge anzeigen (Anzahl: 3)
Anhang 42695

Anhang 42696

Anhang 42697
Zitat:

Zitat von mm1256 (Beitrag 1293155)
Zitat:

Zitat von danieldelphi (Beitrag 1293149)
gebnau das ist ja der ausgangspunkt, so ist am ende der arbeitsspeicher mit der einzulesesnden datei gefüllt.

Aber genauso mach ich das schon jahrelang mit großen Textdateien ohne Probleme. Schau dir deinen Code genauer an, da musst du ein Problem haben.

Was soll z.B. das...wenn angenommen "Zeile" eine Stringvariable ist:

Delphi-Quellcode:
//BG2010: Wenn Zeile mit Hochkomma beginnt, dann Einlesevorgang abbrechen...
      if zeile[0] = '''' then break;

naja das ist einfach dafür da, dass abgebrochen wird, wenn eine leere zeile dabei ist. also ich habe den code soweit runter gbrochen wie es geht, also oben mal als anhang und der arbeitsspeicher wächst.

danieldelphi 12. Mär 2015 10:59

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Mavarik (Beitrag 1293156)
Hast Du das mal mit {$R+,O+} compiliert?

nein hab ich nicht, was tut das?

danieldelphi 12. Mär 2015 11:01

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von baumina (Beitrag 1293157)
Vielleicht hilft ja auch das hier weiter SJ MMF File Reader - Schneller Textdatei Reader

danke das versuch ich mal, aber ich glaub dass das nicht ganz dem entspricht was ich brauche.

Mavarik 12. Mär 2015 11:09

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von danieldelphi (Beitrag 1293158)
Delphi-Quellcode:
//BG2010: Wenn Zeile mit Hochkomma beginnt, dann Einlesevorgang abbrechen...
      if zeile[0] = '''' then break;

Also Zeile[0] ist, wenn Du nicht gerade auf iOS oder Andoid bist das Längenbyte!

und R+ O+ kannst Du auch unter Compiler einstellen...
Bereichsüberprüfung und Überlauf...

Mavarik

mm1256 12. Mär 2015 11:11

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von danieldelphi (Beitrag 1293153)
Zitat:

Zitat von Mavarik (Beitrag 1293150)
Zitat:

Zitat von danieldelphi (Beitrag 1293142)
das ist delphi 6.

hmm cool

Unter Delphi 6 ist ein String immer ein Shortstring... Oder verwechsele ich da gerade etwas? Ist zu lange her...

Bist Du sicher, das Deine Zeilen in den Textdateien kürzer als 255 Zeichen sind?

Mavarik

ich bin mir nicht sicher, bzw ich weiß, dass die zeieln teilweise über 300 zeichen haben, aber zeile ist bei mir auch ein char array mit 500 zeichen den ich dann in der procedure in einen string umwandel, siehst du da ein problem dass ich nicht sehe?

Und warum liest du nicht gleich einen String ein? Ich denke, hier (in der Umwandlung) liegt dein (Speicher-)Problem

p80286 12. Mär 2015 11:36

AW: Memory leak durch funktion readln
 
Irgendwann hab ich aufgegeben mich durch dieses Dateichaos zu wühlen.
Den Sourcen würde eine logische überarbeitung und vor allem Auftrennung ganz gut tun.
wenn das Einlesen/Schreiben der Strings nicht so richtig fluppt, wie wäre es
Delphi-Quellcode:
textbuf
zu nutzen? so zwischen 8k und 16k puffergroße ist man ganz gut unterwegs.

Ein
Delphi-Quellcode:
if string[0]=''''
ist nicht soo dolle weil man in diesem Falle (bei shortstrings) nachfragt ob der String 39 Zeichen lang ist.

Gruß
K-H

@Mavarik
warum auch immer, aber seit D7 ist das read über ein filestream schneller als ein blockread.

Mavarik 12. Mär 2015 11:44

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von p80286 (Beitrag 1293174)
@Mavarik
warum auch immer, aber seit D7 ist das read über ein filestream schneller als ein blockread.

Nöö... Debug dich mal durch... Der FileStream hat 3 Calls mehr bevor er genau in die selbe Routine springt wie der Blockread.

Mavarik

danieldelphi 12. Mär 2015 12:00

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von mm1256 (Beitrag 1293166)
Zitat:

Zitat von danieldelphi (Beitrag 1293153)
Zitat:

Zitat von Mavarik (Beitrag 1293150)
Zitat:

Zitat von danieldelphi (Beitrag 1293142)
das ist delphi 6.

hmm cool

Unter Delphi 6 ist ein String immer ein Shortstring... Oder verwechsele ich da gerade etwas? Ist zu lange her...

Bist Du sicher, das Deine Zeilen in den Textdateien kürzer als 255 Zeichen sind?

Mavarik

ich bin mir nicht sicher, bzw ich weiß, dass die zeieln teilweise über 300 zeichen haben, aber zeile ist bei mir auch ein char array mit 500 zeichen den ich dann in der procedure in einen string umwandel, siehst du da ein problem dass ich nicht sehe?

Und warum liest du nicht gleich einen String ein? Ich denke, hier (in der Umwandlung) liegt dein (Speicher-)Problem

warum sollte das einen unterschied machen? ja gut ich versuch es mal.

mm1256 12. Mär 2015 12:01

AW: Memory leak durch funktion readln
 
Aber wenn ihr schon Calls zählt, beiden Varianten ist gemeinsam: Die Datenzeile muss erst wieder "manuell" extrahiert werden, und darum ist (meiner Meinung nach) ReadLn(TxtVariable,MeinDatenString) die schnellste Lösung, weil hier die Länge der Stringvariable gleich mit gesetzt wird.

danieldelphi 12. Mär 2015 12:02

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von p80286 (Beitrag 1293174)
Irgendwann hab ich aufgegeben mich durch dieses Dateichaos zu wühlen.
Den Sourcen würde eine logische überarbeitung und vor allem Auftrennung ganz gut tun.
wenn das Einlesen/Schreiben der Strings nicht so richtig fluppt, wie wäre es
Delphi-Quellcode:
textbuf
zu nutzen? so zwischen 8k und 16k puffergroße ist man ganz gut unterwegs.

Ein
Delphi-Quellcode:
if string[0]=''''
ist nicht soo dolle weil man in diesem Falle (bei shortstrings) nachfragt ob der String 39 Zeichen lang ist.

Gruß
K-H

@Mavarik
warum auch immer, aber seit D7 ist das read über ein filestream schneller als ein blockread.

das string[0] ist nicht so wichtig, textbuf werd ich auch mal versuchen,


daaaaanke fpr eure schnellen ausführlichen antworten! super forum! daaaanke.
ich schreib nochmal morgen, hab jetzt n paar meetings. viele grüße

Mavarik 12. Mär 2015 12:14

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von mm1256 (Beitrag 1293182)
Aber wenn ihr schon Calls zählt, beiden Varianten ist gemeinsam: Die Datenzeile muss erst wieder "manuell" extrahiert werden, und darum ist (meiner Meinung nach) ReadLn(TxtVariable,MeinDatenString) die schnellste Lösung, weil hier die Länge der Stringvariable gleich mit gesetzt wird.

Delphi macht intern nix anderes...

Kommt darauf an, ob und was ich mit dem String machen will...

mm1256 12. Mär 2015 12:26

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Mavarik (Beitrag 1293186)
Kommt darauf an, ob und was ich mit dem String machen will...

Na ja, das wissen wir doch, seitdem er seinen Code geposted hat. Die Längenermittlung der eingelesenen Daten (CR, LF, CRLF oder EOF) der System.pas zu überlassen finde ich jedoch schon eine gute Idee.

Jasocul 12. Mär 2015 12:31

AW: Memory leak durch funktion readln
 
Naja, wenn ich es richtig sehe, bekommt "autodatei" kein Close.
Das mag Windows überhaupt nicht, weil dadurch File-Handles nicht wieder freigegeben werden. Das kann in der Folge dann auch zu Memory-Leaks führen.

Mal abgesehen davon, dass in der inneren While-Schleife ein Exit steht. Wodurch keine einzige Datei-Variable mehr freigegeben wird.

Oder habe ich das Close für autodatei übersehen?

mm1256 12. Mär 2015 12:47

AW: Memory leak durch funktion readln
 
Richtig, das sind zwei weitere Probleme. Aber, der TE hat doch mit FastMM geprüft. Müsste der dann nicht anschlagen?

Jasocul 12. Mär 2015 12:51

AW: Memory leak durch funktion readln
 
Weiß ich nicht sicher, da ich mich mit FastMM nicht besonders gut auskenne.
Allerdings ist das mit den File-Handles in dieser Konstellation meines Wissens ein Windows-Problem. Das könnte evtl. an FastMM vorbei gehen.

EDIT:
Zitat:

Zitat von danieldelphi (Beitrag 1293132)
Dann hab ich weiter gesucht und iwo gelesen, dass FastMM keine leaks bezüglich externer Datein findet, ...


p80286 12. Mär 2015 15:47

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von Jasocul (Beitrag 1293189)
Naja, wenn ich es richtig sehe, bekommt "autodatei" kein Close.
Das mag Windows überhaupt nicht, weil dadurch File-Handles nicht wieder freigegeben werden. Das kann in der Folge dann auch zu Memory-Leaks führen.

Sag ich doch, Chaos!
Das letzte mal, als ich so wilde Dateioperationen durchgeführt habe, war noch kein Delphi existent.

[OT]
@Mavarik glaub ich Dir gerne, aber da die Blockwrite/Blockread-s definitv langsamer waren als das Filestream.Read/write, hab ich alles umgestellt (seit D7/XP) u.U. gibt es da ja noch ein paar Nebensächlichkeiten, die sich auswirken!?)
[/OT]

Gruß
K-H

FaTaLGuiLLoTiNe 12. Mär 2015 16:28

AW: Memory leak durch funktion readln
 
Eine wesentliche Verbesserung des gezeigten Quelltextes würde - wohl auch im Hinblick auf das Thema dieses Threads - in der Verwendung von Ressourcenschutzblöcken bestehen...

Mavarik 12. Mär 2015 22:14

AW: Memory leak durch funktion readln
 
Zitat:

Zitat von p80286 (Beitrag 1293241)
[OT]
@Mavarik glaub ich Dir gerne, aber da die Blockwrite/Blockread-s definitv langsamer waren als das Filestream.Read/write, hab ich alles umgestellt (seit D7/XP) u.U. gibt es da ja noch ein paar Nebensächlichkeiten, die sich auswirken!?)
[/OT]

hmm... Wüste nicht was, aber nix was man nicht mal testen kann... (Dir zu liebe):stupid:

Lesen von 5.291.584 KB - gelesen in Häppchen zu 1.048.576 KB

Versuch 0 : ohne Wertung wegen Windows Cache lesen.

Versuch 1 : Blockread(1405 ms) StreamRead(1408 ms) 1:0
Versuch 2 : Blockread(1414 ms) StreamRead(1404 ms) 1:1
Versuch 3 : Blockread(1411 ms) StreamRead(1408 ms) 1:2
Versuch 4 : Blockread(1416 ms) StreamRead(1407 ms) 1:3
Versuch 5 : Blockread(1406 ms) StreamRead(1409 ms) 2:3
Versuch 6 : Blockread(1421 ms) StreamRead(1423 ms) 3:3
Versuch 7 : Blockread(1423 ms) StreamRead(1417 ms) 3:4
Versuch 8 : Blockread(1407 ms) StreamRead(1411 ms) 4:4
Versuch 9 : Blockread(1408 ms) StreamRead(1410 ms) 5:4

Ätsch Blockread hat mit 5:4 gewonnen...

Gemessen in einer Windows 7/64 VMWare


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:57 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