Entwickler-Ecke

Sonstiges (Delphi) - IntToStr - Speicherlecks?


P_G - Di 22.07.08 11:51
Titel: IntToStr - Speicherlecks?
Hallo zusammen,

Ich habe von http://www.Delphi3000.com einen simplen Code getestet, um Speicherlecks aufzuspüren. Dabei bin ich auf ein merkwürdiges Verhalten beim Einsatz von IntToStr gestoßen.

Der Code sieht folgendermaßen aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TForm1.Button1Click(Sender: TObject);
var
  Point1,Point2:Integer;
  IsLeak:Boolean;
  tmpInt: string;
begin
 Point1:=AllocMemSize; //Hold Allocated Memory size

 tmpInt := IntToStr(10); // Ergibt ein Speicherleck
// tmpInt := '10';            // Ergibt kein Speicherleck

 Point2:=AllocMemSize-Point1; //Get the differrent of                       //allocated memory size
    //between two Points of code

  if Point2<>0 then
    ShowMessage('We have ' + IntToStr(Point2)+' byte as memory leak ')
end;


Schreibe ich tmpInt := IntToStr(10) ergibt sich ein Speicherleck von 12 byte.
Kommentiere ich diese Zeile hinaus und weise dem String über tmpInt := '10' einen Wert zu, kommt es zu keinem Speicherleck.
Hat jemand eine Erklärung dazu?

Gruß, P_G


Christian S. - Di 22.07.08 11:53

Mein Tipp: Wenn Du den String direkt zuweist, optimiert der Compiler das weg, weil er "weiß", dass der String nicht mehr benutzt wird. Benutzt Du eine Funktion, kann es sein, dass diese Seiteneffekte hat und die Zeile wird nicht wegoptimiert.

Warum es ein Speicherleck sein soll, wenn eine Variable Speicher verbraucht, leuchtet mir aber nicht ein. Irgendwo müssen die Informationen ja gespeichert werden. :nixweiss:


Lossy eX - Di 22.07.08 12:43

Da habe ich noch eine Ergänzung zu Christians Aussage. Wenn der Compiler diese Zeile nicht wegoptimiert, dann ist es richtig. Irgendwo müssen die Informationen ja abgespeichert werden. ABER es ist kein Speicherloch. Diese Messmethode berücksichtigt nämlich leider nicht die Eigenarten von Strings. Es gibt dynamische und statische (konstante) Strings.

Konstante Strings sind etwas wie 'Blahh'. Das wird als Daten hinter die Methode in gepackt. Diese Texte sind als dauerhaft vorhanden. Beim Zuweisen wird diese Konstante lediglich deinem String zugewiesen.

Dynamische Strings (wie bei IntToStr) verfügen über eine Referenzzählung. Wird ein String benutzt wird sie erhöht. Wird er nicht mehr benutzt wird sie verringert. Ist sie bei 0 angelangt wird der String gelöscht. Das irritierende an dieser Zählung ist aber, dass sie am Ende der Methode erst verringert wird. Und das macht der Kompiler ganz automatisch. Und vor allem wirklich als Letztes in der Methode. DU kannst in einer Methode KEINEN Code schreiben der nach dieser Stringfreigabe ausgeführt wird. Entsprechend existiert der String zum Zeitpunkt der Messung noch. Erst wenn die Methode beendet wurde wird der String gelöscht. Oder aber du weißt dem String selber '' (leerstring) zu. Dann wird er auch freigegeben. Aber das selber zu machen ist doppelt gemoppelt, da das am Ende der Methode sowieso passiert. Also mehr Arbeit für den Rechner als nötig.


P_G - Di 22.07.08 13:36

user profile iconLossy eX hat folgendes geschrieben:
Oder aber du weißt dem String selber '' (leerstring) zu. Dann wird er auch freigegeben. Aber das selber zu machen ist doppelt gemoppelt, da das am Ende der Methode sowieso passiert. Also mehr Arbeit für den Rechner als nötig.


Ist mir auch aufgefallen (wenn man beide Zeilen in der obigen Reihenfolge drinläßt ergibt sich nämlich auch kein Problem).
Die Erklärung leuchtet mir ein - auch wenn das leider heißt, daß der Code als Speicherleckmanager nicht viel taugt.

Danke und Gruß, P_G


alzaimar - Di 22.07.08 13:38

Besorg Dir einfach FastMM, dann hast Du deinen Speichleck-Aufspür-O-Mat. Und 'etwas' schneller werden deine Anwendungen auch.


Fabian E. - Di 22.07.08 14:40

user profile iconalzaimar hat folgendes geschrieben:
Besorg Dir einfach FastMM, dann hast Du deinen Speichleck-Aufspür-O-Mat. Und 'etwas' schneller werden deine Anwendungen auch.

Bei mir grade ne ganze Sekunde :) ;) Klingt für manche vielleicht nicht viel, ist es aber :)