Entwickler-Ecke

Internet / Netzwerk - TIDHttp.get - Speicherfresser?


Sy- - Do 01.02.07 11:15
Titel: TIDHttp.get - Speicherfresser?
Hi all,

habe hier in einem Thread ein IDHttp welches ständig Seiten abruft.
Kann mir einer Verraten warum dieser Abschnitt mir die ganze Zeit Speicher Frisst?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  html:string;
...

  try
    html:=http.Get(url);  //<< hier kommt immer wieder die größe der Seite auf den Speicher hinzu!
  except
    result:=-1;
    exit;
  end;


die komponente wird immer wieder neu erstellt und jeweils natürlich auch .free und :=nil

Grüße


jaenicke - Do 01.02.07 11:25

Hmm, sollte zwar eigentlich nicht notwendig sein, aber du kannst ja mal versuchen mit html := ''; den String explizit zu leeren.

Das Get wird den Speicher jedenfalls wohl nicht behalten, aber das kannst du ja testen indem du nur Get aufrufst ohne das Ergebnis in den String zu packen. Ich nehme mal an, dass dann die Speicherauslastung nicht zunimmt.
Was passiert ist ja: Der Speicher wird belegt, und dann hast du in html einen Pointer darauf. Sobald du html aber wieder einem neuen String (aus Get) zuweist, sollte eigentlich der Referenzzähler des Strings auf 0 gehen und der String im Speicher freigegeben werden.


Narses - Do 01.02.07 12:10

Moin!

Ich habe auch schonmal Erfahrung mit komischen Effekten bei dynamischen Variablen in Threads gemacht... :? Das Thema scheint sehr viel komplexer zu sein, als es aussieht. :(

Zum einen hier mal was aus der DOH dazu:
Delphi-Online-Hilfe hat folgendes geschrieben:
Thread-Variablen (oder Thread-lokale Variablen) finden in Multithread-Anwendungen Verwendung. Eine Thread-Variable entspricht in etwa einer globalen Variablen, die einzelnen Ausführungs-Threads erhalten jedoch eine eigene, private Kopie der Variablen, auf die andere Threads keinen Zugriff haben. Thread-Variablen werden nicht mit var, sondern mit threadvar deklariert. Ein Beispiel:

threadvar X: Integer;

Die Deklaration einer Thread-Variablen

darf nicht innerhalb einer Prozedur oder Funktion erfolgen.
darf keine Initialisierungen enthalten.
darf nicht die Direktive absolute enthalten.

Dynamische Variablen, die normalerweise vom Compiler verwaltet werden (lange Strings, Strings des Typs WideString, dynamische Arrays, Varianten und Schnittstellen), können mit der Direktive threadvar deklariert werden. Der Compiler gibt aber den auf dem Heap belegten Speicher (der von den einzelnen Ausführungs-Threads reserviert wird) nicht automatisch frei. Wenn Sie diese Datentypen in Thread-Variablen verwenden, müssen Sie selbst für die Freigabe des Speichers innerhalb des Threads sorgen, bevor dieser beendet wird. Ein Beispiel:

threadvar S: AnsiString;
S := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
...
S := ''; // Den von S belegten Speicher freigeben

Hinweis

Die Verwendung solcher Konstrukte wird nicht empfohlen.

Sie können Varianten freigeben, indem Sie ihnen den Status Unassigned zuweisen. Um Schnittstellen oder dynamische Arrays freizugeben, weisen Sie ihnen den Wert nil zu.)

Und dann gibt es noch diverse spannende Dinge, die man darüber nachlesen kann Suche bei Google DELPHI THREAD HEAP

Weiterhin scheint es deutlich besser zu sein, wenn man direkt "speicheroptimiert" konzeptioniert. In deinem Fall:

Fazit: Threads und dynamische Variablen mit dem Delpih-MM sind ein ziemlich komplexes Thema. 8)

cu
Narses


jaenicke - Do 01.02.07 12:17

Gilt das nicht nur, wenn man die Variablen auch mit threadvar deklariert? Das ist doch was anderes. Ich meine, solange der Thread nur einmal läuft, braucht mal die ja auch nicht, dann kann man ja normale globale Variablen nutzen. Schwierig wird das ja erst, wenn der Thread mehrfach läuft. Erst da kommen ja Thread-Variablen ins Spiel.

Dass dies zur Informationsweitergabe aus einem Thread nur bedingt tauglich ist, ist noch ne ganz andere Sache...


Narses - Do 01.02.07 13:31

Moin!

user profile iconjaenicke hat folgendes geschrieben:
Gilt das nicht nur, wenn man die Variablen auch mit threadvar deklariert?

Klar, war auch nur für den Fall von mir zitiert, dass es verwendet wird. ;)

user profile iconjaenicke hat folgendes geschrieben:
Das ist doch was anderes. Ich meine, solange der Thread nur einmal läuft, braucht mal die ja auch nicht, dann kann man ja normale globale Variablen nutzen. Schwierig wird das ja erst, wenn der Thread mehrfach läuft. Erst da kommen ja Thread-Variablen ins Spiel.

Nun, du kannst auch bei mehrfacher Ausführung eines Threads mit lokalen Variablen des Thread-Objekts (TThread-Descendants) arbeiten. Globale Variablen für Threads scheinen mir allerdings generell NIE eine gute Idee zu sein... :? ;)

cu
Narses