![]() |
Extremer Speicherfraß durch Strings/StringLists (?)
Also, mein Problem ist folgendes:
Ich habe ein Programm welches Informationen einliest aus TEmbeddedWB. (ach nee ;) Mit SaveToStrings speichere ich den Source der Seite in einer TStringList die jedes mal Lokal erstellt und wieder gefreet wird. (Ich bin mir ziemlich sicher, dass ich das try..finally Konstrukt richtig anwende und bei jedem UP-Aufruf wird die Codezeile mit .Free auch abgearbeitet) Ich verwende sakura's Funktion NextPos um relevante Daten im Source zu finden und lege die in einem Array[1..5] of AnsiString (global) ab. Nach einer bestimmten Anzahl von Aufrufen, speichere ich den Inhalt des Strings in einer Textdatei per Append und mache dann z.B. sMyString[1] := ''; um den String wieder freizugeben. Mache ich damit schonmal was falsch? (Und bitte, fragt mich nicht warum ich so'n Scheiss mit dem Array mache, nehmt einfach an es ginge nicht anders. ;) Tjo, sonst gibt es da noch 2 StringLists, aber die enthalten nicht wirklich viel (max 50KB zusammen) und werden bei Start des Programmes created und bei Beenden gefreet. Viel mehr Variablen (ausser vielleicht ein bis zwei Schleifenvariablen) habe ich nicht und kann mir nicht erklären, wie das Programm so derbe viel Speicher fressen kann. (Da muss irgendwo ein schwarzes Loch drin sein) Ich habe es mal eine Stunde laufen lassen (ja, es gab schon einiges zu tun ;) und gegen Ende nutze es 540MB und das Tolle ist, die relevanten Daten, gespeichert in der Textdatei, brauchten am Ende nur ~700KB. Das ist doch ein erstaunlich großer Unterschied und daher dachte ich mir, frage ich mal hier, vielleicht weiss jemand Rat. Ich kann mir nämlich nur noch an den Kopf fassen. |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Moin nTE,
ein bisschen Source wär' nicht schlecht. ;-) |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Oh nein, das habe ich befürchet.
Ähm.. also der Code ist wirklich ausgesprochen hässlich und ich hoffe mir ist niemand böse, wenn ich ihn auf das Wesentliche beschränke in der Darstellung hier. :P
Delphi-Quellcode:
Diese Prozedur wird von TEmbeddedWB.OnDownloadComplete aufgerufen und nachdem ich es mal ein paar Stunden laufen ließ, wurde sie bestimmt an die 40000 Mal aufgerufen.
procedure Scan(Sender: TObject; sSearchStr);
var i, j: Integer; sSource: TStringList; iPos: Cardinal; TempStr: AnsiString; DF: Textfile; begin if Sender is TEmbeddedWB then begin sSource := TStringList.Create; try with Sender as TEmbeddedWB do SaveToStrings(sSource); iPos := 0; // jetzt kämen zwei for-schleifen :P //for i := ... //for j := ... begin iPos := NextPos(sSearchStr, sSourceText, iPos + 1); TempStr := Copy(sSource.Text, iPos, 250); // kopiert die relevante Information (bis zum nächsten '<') // übrigens, da Length Integer und NextPos Cardinal zurückliefert, bekomme ich.. // ..bei jedem Aufruf dieser Art "Vorzeichenbehaftete und -lose Typen werden kombiniert.." // aber dagegen kann ich wohl nichts machen oder? ^^; TempStr := Copy(TempStr, 1, Length(TempStr) - (Length(TempStr) - NextPos('<', TempStr, 1) + 1)); Lines[i] := Lines[i] + TempStr; // es folgen weitere 2-3 (je nach if Resultat) solcher Zeilen :P // ... end; // das Speichern des Inhaltes, ab und zu mal (if Verzweigung) begin for i := 2 to 5 do begin Lines[1] := Lines[1] + Lines[i]; Lines[i] := ''; end; AssignFile(DF, SAVE_FILE); Append(DF); Write(DF, Lines[1]); Flush(DF); CloseFile(DF); Lines[1] := ''; end; with Sender as TEmbeddedWB do // URL wird abhängig von den gefundenen Ergebnissen verändert um sich durchzunavigieren :P Navigate(URL); finally sSource.Free; end; end; end; Mmh.. also ich könnte verstehen wenn euch meine Art meinen Code zu präsentieren gelinde gesagt zu blöd ist, aber ich würde mich trotzdem immer über Hilfe freuen. ;) [edit=Daniel B]Delphi-Tags korrigiert. Mfg, Daniel B[/edit] |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Also.....ich kenn zwar das Problem nicht. Aber 3 Dinge sind mir aufgefallen.
1. Diese Codezeile
Code:
der String wird die befüllt (length(tempstr)-length(tempstr)) = 0 - nochwas ergibt negativen wert...!!!
TempStr := Copy(TempStr, 1, Length(TempStr) - (Length(TempStr) - NextPos('<', TempStr, 1) + 1));
2. sSource wird immer wieder neu erzeugt....-> ineffektiv Lieber am Programmstart create, am ende free und hier immer nur ssource.clear; 3.Datei Assign, Append und Close würd ich ebenfalls außerhalb machen. Das frist auch ewig zeit. Obwohl ich auch einiges mit TStrings/TStringlist mach, hab ich bisher nix feststellen können, das da irgendwelche Speicherleaks auftreten. Propier mal ob du vielleicht mit dem Programm "Memproof" was rausfindest. ![]() |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Liste der Anhänge anzeigen (Anzahl: 1)
Erstmal danke für die Antwort, ich habe mir alles mal angeschaut was du gesagt hast (vor allem MemProof) und habe folgendes zu berichten:
Zu 1. Ich überprüfe vorher (sorry, hab ich nicht aufgeführt) ob iPos > 0 ist (also ob überhaupt was gefunden wurde) und der hintere Teil ist nicht "(length(tempstr)-length(tempstr))" sondern "Length(TempStr) - (Length(TempStr) - NextPos('<', TempStr, 1) + 1)" und daher wird das nie kleiner Null, ausser in ganz TempStr befindet sich kein '<', was ich aber Aufgrund der Kentnisse über die zu erfassende Struktur ausschließen kann. (Es ist sicher immer möglich und schlecht programmiert sowieso, soviel ist sicher =) Zu 2. Guter Tipp, habe ich gleich mal geändert. Zu 3. Ok, wenn kein Memory mehr leakt, werde ich das alles in einem Schwung in die Datei schreiben (sind ja wie gesagt nur ~700KB). =) So, erstmal vorneweg, das Programm verwendet schon 6.5 MB nach dem Start. Ich würde das Speicherloch eindeutig dem Internet Explorer zuschieben. Wie in der angehangenen Datei zu erkennen, sind die meisten (äh, fast alle?) Fehler beim Speicherfreigeben unter Beteiligung von mshtml.dll und shdocvw.dll. Ich benutze IE 5.0 unter Win2k mit SP3, d.h. IE 5.00.3502.1000 (128-Bit). Ich habe schon ein wenig über Leaks im IE 5 gefunden auf der Microsoft-Page aber die sollen angeblich mit IE 5.0 SP3 behoben worden sein. Müsste ich jetzt auf IE 6 umsteigen (was ich nur seeehr ungern würde) und kann es dabei mit meinem Programm Probleme geben? =) |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Moin nTE,
so unmittelbar ist nichts zu sehen :? Da ich jetzt TEmbeddedWB nicht habe: Wo kann ich mal eine Doku zu SaveToStrings nachlesen? Im Moment habe ich diese Methode im Verdacht. |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Auf der Page steht nur, dass SaveToStrings den Source nach TStrings speichert. :P
![]() Daher habe ich mal das Nötige rauskopiert (hoffe ich).
Delphi-Quellcode:
In der oberen Funktion habe ich die beiden Codezeilen auskommentiert, da sonst SaveToStrings nie funktioniert, wenn z.B. ein JavaScript ständig den Inhalt ändert (z.B. bei einem Counter oder einer Uhr).
function TEmbeddedWB.SaveToStrings(AStrings: TStrings): HRESULT;
begin // while ReadyState <> READYSTATE_COMPLETE do // Forms.Application.ProcessMessages; if Assigned(document) then Result := SaveDocToStrings(Document, AStrings) else Result := S_FALSE; end; function SaveDocToStrings(Doc: IDispatch; var AStrings: TStrings): HResult; var IpStream: IPersistStreamInit; AStream: TMemoryStream; begin AStream := TMemoryStream.Create; try IpStream := doc as IPersistStreamInit; if not Assigned(IpStream) then Result := S_FALSE else if Succeeded(IpStream.save(TStreamadapter.Create(AStream), TRUE)) then begin AStream.Seek(0, 0); AStrings.LoadFromStream(AStream); Result := S_OK; end else Result := S_FALSE; except Result := S_FALSE; end; AStream.Free; end; Ausserdem funktioniert SaveFrameToStrings auch ohne das. ;) |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Moin nTE,
mal abgesehen davon, dass AStream dort nicht mit einem try/finally Block geschützt ist, bei einer Exception der MemoryStream nicht wieder freigegeben wird, kann ich auch da nichts finden. |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Da ich immer (hab's überprüft ;) einen String zurückbekomme kann man wohl ausschließen, dass eine Exception aufgetreten ist, oder?
Wenn dem so ist, würde ich es echt auf die shdocvw.dll/mshtml.dll schieben. ;) |
Re: Extremer Speicherfraß durch Strings/StringLists (?)
Okay, ich habe es einfach mal mit sSource.LoadFromFile als Ersatz probiert (den Rest so gelassen), um festzustellen ob es an SaveToStrings liegt und du hattest Recht Christian, da ist der Wurm drin.
Ich habe mal geschaut was bei TEmbeddedWB so falsch sein könnte und bin bisher nur auf das gestoßen:
Delphi-Quellcode:
constructor TEmbeddedWb.Create(Owner: TComponent);
var Buf: array[1..10] of Char; begin FfpExceptions := True; inherited; {$IFDEF VER120} enablemessagehandler; {$ENDIF} GetDDEVariables; // Compiler: Symbol 'AllocateHWnd' wird abgelehnt DDEHWnd := AllocateHWnd(DDEWndProc); . . . end; destructor TEmbeddedWb.Destroy; begin // Compiler: Symbol 'DeAllocateHWnd' wird abgelehnt DeAllocateHWnd(DDEHwnd); . . . end; // Folgendes aus function SaveDocToStrings(Doc: IDispatch; var AStrings: TStrings): HResult; // mehr Quelltext, siehe oben ;) IpStream := doc as IPersistStreamInit; // wird nicht wieder freigegeben? naja, ich hab mal ._Release damit gemacht und es hat nichts gebracht if Succeeded(IpStream.save(TStreamadapter.Create(AStream), TRUE)) // TStreamadapter hat noch die Eigenschaft Ownership die hier nicht verwendet wird: // Mit Ownership wird die Eigenschaft StreamOwnership initialisiert, die das verantwortliche TStreamAdapter-Objekt für die Freigabe des in Stream angegebenen Streams im eigenen Destruktor bezeichnet. // Mehr fällt mir langsam echt nicht mehr ein. Ich suche momentan noch ein wenig nach Lösungen, aber ich glaube bald lege ich das Programm einfach unter RAM-Hog ab und fass es nicht mehr an. ;) Ich habe leider keine andere OpenSource TWebBrowser Komponente gefunden, vielleicht hat da ja jemand was für mich? :P Ach ja, vielleicht könnte ein Mod ja das Thema in "Memory Leak in TEmbeddedWB (SaveTo...)" umbenennen und nach "Internet / IP / LAN" verschieben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:00 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