![]() |
Speicherüberlauf?
Hab ein Programm geschrieben, welches nach einer ganze Liste von Dateinamen suchen kann. Wenn ich ein Duzend Dateinamen eingebe, läuft alles reibungslos. Gebe ich aber ein paar hundert Dateinamen ein, stürzt das Programm ab. Vielleicht läuft der Speicher über!?
Hier der Auszug um die Suchprozedur:
Delphi-Quellcode:
Kann mir jemand helfen?
procedure GetAllFiles (Mask_: String; Items_: TStrings);
const FileAttr = faReadOnly+faHidden+faArchive; var Search: TSearchRec; SFName: String; SFPath: String; begin SFName := ExtractFileName(Mask_); SFPath := ExtractFilePath(Mask_); if SFPath[Length(SFPath)]<>'\' then SFPath := SFPath+'\'; // alle Dateien suchen if FindFirst(Mask_, FileAttr, Search)=0 then begin repeat begin Items_.Add(SFPath+Search.Name) end until FindNext(Search)<>0 end; // Unterverzeichnisse durchsuchen if FindFirst(SFPath+'*.*',faDirectory,Search)=0 then begin repeat begin if ((Search.Attr and faDirectory)=faDirectory) and (Search.name[1]<>'.') then begin // Selbstaufruf von GetAllFiles GetAllFiles(SFPath+Search.Name+'\'+SFName,Items_) end end until FindNext(Search)<>0 end; FindClose(Search); end; procedure TForm1.btnSuchenClick(Sender: TObject); var Suchobjekt: String; i, i0: Integer; test: tmsgdlgbtn; begin If Edit1.Text = 'Zu durchsuchendes Verzeichnis' then begin OrdnerauswahlClick; end else If Memo1.Lines[0] = 'Bitte geben Sie das/die zu suchende(n) Objekt(e) ein!' then begin Showmessage('Bitte geben Sie das/die zu suchende(n) Objekt(e) ein!'); end else begin screen.Cursor := crHourglass; For i := 0 to Memo1.Lines.Count-1 do begin Suchobjekt := Memo1.Lines[i]; If not CheckBox1.Checked then begin Suchobjekt := '*' + Suchobjekt + '*'; end; GetAllFiles (Edit1.Text + '\' + Suchobjekt, clbSuchergebnisse.Items); end; If clbSuchergebnisse.Items.Count = 0 then StatusBar1.Panels[0].Text := 'Es wurden keine Objekte gefunden.'; If clbSuchergebnisse.Items.Count = 1 then StatusBar1.Panels[0].Text := 'Es wurde 1 Objekt gefunden.'; If clbSuchergebnisse.Items.Count > 1 then StatusBar1.Panels[0].Text := 'Es wurden ' + IntToStr(clbSuchergebnisse.Items.Count) + ' Objekte gefunden.'; For i := Memo1.Lines.Count+1 downto 1 do begin For i0 := 1 to clbSuchergebnisse.Count do begin If Memo1.Lines[i-1] = ExtractFileName(clbSuchergebnisse.Items[i0-1]) then begin Memo1.Lines.Delete(i-1); end; end; end; screen.Cursor := crDefault; end; end; |
Re: Speicherüberlauf?
Du musst neben dem Verzeichnisnamen "." auch ".." abfangen !!
Ansonsten geht deine Prozedure über ".." ein Verzeichnis nach oben, grasst alle Dateien ab, findet ein echtes Verzeichnis, durchläuft dieses, findet "..", geht rekursiv nach oben.... Ein :twisted: Teufelskreis :twisted:. |
Re: Speicherüberlauf?
Zitat:
|
Re: Speicherüberlauf?
Zitat:
|
Re: Speicherüberlauf?
Also, ich bin mir gar nicht so sicher, dass es an der Suchroutine selber liegt. Hab die nicht selber geschrieben, sondern einfach ausem INet geklaut.^^ Aber vorher hatte ich eine andere und mit der hatte ich das gleiche Problem. Ich bin da einfach ratlos. Denn in der OnClick-Prozedur find ich nichts, was diesen Fehler rechtfertigt.
|
Re: Speicherüberlauf?
Moin Stamper,
also mir fallen da, auf Anhieb, ein paar unschöne Stellen auf ;-) Erstens:
Delphi-Quellcode:
Flags niemals mit + verknüpfen, sondern immer mit or.
const
FileAttr = faReadOnly+faHidden+faArchive; Das hat hier zwar keine Auswirkungen, aber besser Du gewöhnst Dir das + gar nicht erst an (ich weiss, in der Delphi-Hilfe steht es auch mit +, aber dadurch wird's nicht besser ;-)) Hintergrund: Sollte bei verschiedenen Konstanten mal das gleiche Bit gesetzt sein, so erhält man bei +, unter Umständen, eine ungültige oder, schlimmer noch, unerwünschte Bitmaske. Bei or kann das nicht passieren.
Delphi-Quellcode:
Zweitens:
const
FileAttr = faReadOnly or faHidden or faArchive; Das hier:
Delphi-Quellcode:
kann schief gehen, wenn die Länge von SFPath gleich 0 ist.
if SFPath[Length(SFPath)]<>'\' then SFPath := SFPath+'\';
Besser wäre die Verwendung von IncludeTrailingPathDelimiter oder IncludeTrailingBackslash. Drittens: Zumindest beim ersten erfolgreich ausgeführten FindFirst fehlt das zugehörige FindClose. Ausserdem fehlen jeweils die Resourcenschutzblöcke (try/finally)
Delphi-Quellcode:
Viertens:
if FindFirst ... = 0 then begin
try finally FindClose... end; end; Diese Prüfung:
Delphi-Quellcode:
ist schlicht falsch, da Datei und Verzeichnisnamen mit einem Punkt beginnen dürfen.
(Search.name[1]<>'.')
Es müssen explizit die Namen . und .. geprüft werden.
Delphi-Quellcode:
(Search.Name <> '.') and (Search.Name <> '..')
|
Re: Speicherüberlauf?
Moin Christian,
da hab ich lange drauf gewartet, aber ich wollte Dir nicht vorgreifen :zwinker: |
Re: Speicherüberlauf?
Ich hab die Tipps von Christian umgesetzt. Hat aber dennoch nicht funktioniert. Aber ihr habt trotzdem richtig gelegen. Ich hab ne neue Suchroutine von
![]() Das sieht jetzt folgendermaßen aus:
Delphi-Quellcode:
Allerdings hängt er etwas bei längeren Listen. Also ich bin hingegangen und hab nach bestimmt 500 bis 600 Dateien suchen lassen, und wenn ich dann mal zwischendurch das Fenster wechsel und dann wieder zurückkehre, sehe ich das ganze Fenster erst mal nur in weiß, und wenn die Suche dann fertig ist, sehe ich aber alles wieder in ordentlicher Form.
procedure GetFilesInDirectory(Directory: String; Fileobject: String;
List: TStrings; WithSubDirs, ClearList: Boolean); procedure ScanDir(const Directory: String); var SR: TSearchRec; begin if FindFirst(Directory + Fileobject, faAnyFile and not faDirectory, SR) = 0 then try repeat List.Add(Directory + SR.Name) until FindNext(SR) <> 0; finally FindClose(SR); end; if WithSubDirs then begin if FindFirst(Directory + '*.*', faAnyFile, SR) = 0 then try repeat if ((SR.attr and faDirectory) = faDirectory) and (SR.Name <> '.') and (SR.Name <> '..') then ScanDir(Directory + SR.Name + '\'); until FindNext(SR) <> 0; finally FindClose(SR); end; end; end; begin List.BeginUpdate; try if ClearList then List.Clear; if Directory = '' then Exit; if Directory[Length(Directory)] <> '\' then Directory := Directory + '\'; ScanDir(Directory); finally List.EndUpdate; end; end; procedure TForm1.btnSuchenClick(Sender: TObject); var Suchobjekt: String; i, i0: Integer; test: tmsgdlgbtn; begin If Edit1.Text = 'Zu durchsuchendes Verzeichnis' then begin OrdnerauswahlClick; end else If Memo1.Lines[0] = 'Bitte geben Sie das/die zu suchende(n) Objekt(e) ein!' then begin Showmessage('Bitte geben Sie das/die zu suchende(n) Objekt(e) ein!'); end else begin screen.Cursor := crHourglass; For i := 0 to Memo1.Lines.Count-1 do begin Suchobjekt := Memo1.Lines[i]; If not CheckBox1.Checked then begin Suchobjekt := '*' + Suchobjekt + '*'; end; GetFilesInDirectory(Edit1.Text, Suchobjekt, clbSuchergebnisse.Items, True, False); end; If clbSuchergebnisse.Items.Count = 0 then StatusBar1.Panels[0].Text := 'Es wurden keine Objekte gefunden.'; If clbSuchergebnisse.Items.Count = 1 then StatusBar1.Panels[0].Text := 'Es wurde 1 Objekt gefunden.'; If clbSuchergebnisse.Items.Count > 1 then StatusBar1.Panels[0].Text := 'Es wurden ' + IntToStr(clbSuchergebnisse.Items.Count) + ' Objekte gefunden.'; For i := Memo1.Lines.Count+1 downto 1 do begin For i0 := 1 to clbSuchergebnisse.Count do begin If Memo1.Lines[i-1] = ExtractFileName(clbSuchergebnisse.Items[i0-1]) then begin Memo1.Lines.Delete(i-1); end; end; end; screen.Cursor := crDefault; end; end; |
Re: Speicherüberlauf?
Das ist normal, weil die Botschaftswarteschlange während der Ausführung nicht abgearbeitet wird. Abhilfe kann hier das Einstreuen von
Delphi-Quellcode:
schaffen, allerdings solltest Du das nicht nach jedem Treffer machen, sondern z.B. nach jedem 50. Dafür brauchst Du dann einen internen Zähler.
Application.ProcessMessages;
|
Re: Speicherüberlauf?
Ja, so was in der Richtung habe ich gesucht. Danke!
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:27 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