AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

MemoryLeaks mit s := I.ToString

Ein Thema von Kraisel · begonnen am 7. Nov 2014 · letzter Beitrag vom 12. Nov 2014
Antwort Antwort
Benutzerbild von Kraisel
Kraisel

Registriert seit: 19. Mär 2012
Ort: Bochum-Linden
64 Beiträge
 
Delphi 12 Athens
 
#1

MemoryLeaks mit s := I.ToString

  Alt 7. Nov 2014, 18:49
Delphi-Version: XE5
Alles mit XE7 Pro
Delphi-Quellcode:
procedure Test;
var
  s1,s2: String;
  i: Integer;
begin
  i := 123;
  s1 := IntToStr(I); // der Referenzzähler von s1 ist hier 1 :-)
  GetDynVarPrms(s1);
  s2 := I.ToString; // der Referenzzähler von s2 ist hier 2 :-(
  GetDynVarPrms(s2);
end;
Delphi-Quellcode:
function GetDynVarPrms (const v): String; // zum einfachen Anzeigen der DynVarParameter auf dem Heap
var p: PInteger;
begin
  p := Pointer((@v)^);
  Result:= 'VarPtr: $' + IntToHex(Integer(@v), 8) + ', BufPtr: ';
  if p <> NIL then begin
    Result := Result + '$' + IntToHex(Integer(p), 8);
    Dec(p);
    Result := Result + ', Len: ' + IntToStr(Integer(p^));
    Dec(p);
    Result := Result + ', RefCntr: ' + IntToStr(Integer(p^));
  end else Result := Result + 'NIL';
end;
Es hat lange gedauert, bis ich wusste, wieso ich beim Beenden des Programms MemoryLeaks angezeigt bekam.
Alle I.ToString mit IntToStr(I) ausgewechselt und alles war wieder OK.

So wie ich das im Moment sehe, wird der Heap bei jedem Aufruf von I.ToString weiter zugemüllt.

Ein "normales" Programm räumt beim Beenden die ganzen verwaisten Variablen wohl einfach wieder auf, und es werden keine MemoryLeaks angezeigt. Wenn man aber z.B. in Threads mit Windows.Fiber arbeitet, bleiben die MemoryLeaks erhalten, und man sieht sie (mit ReportMemoryLeaksOnShutDown := TRUE).

Hat da jemand eine Idee, wieso dass so ist.
Oder habe ich nur Leaks im Hirn?

Danke
Peter Kaisler
Das einzig Komplizierte ist zu begreifen wie einfach es ist.

Geändert von Kraisel ( 7. Nov 2014 um 19:03 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.308 Beiträge
 
Delphi 12 Athens
 
#2

AW: MemoryLeaks mit s := I.ToString

  Alt 7. Nov 2014, 19:11
Dieses komische Rumgepointere solltest du besser lassen

Delphi-Referenz durchsuchenLength
Delphi-Referenz durchsuchenStringElementSize
Delphi-Referenz durchsuchenStringCodePage
Delphi-Referenz durchsuchenStringRefCount

Ansonsten ist es ganz nett (so hatte ich es vor Einführung dieser Funktionen gemacht), wenn man sich einen Record erstellt (kannst dir bei System.StrRec abgucken) und darüber geht.
P := PStringRec(Pointer(S) - SizeOf(PStringRec)); -> P.RefCount


Da gibt es wohl eine Unpässligkeit beim Erzeugen des InlineCodes für TIntegerHelper.ToString.

Code:
Unit2.pas.31: s1 := IntToStr(I); // der Referenzzähler von s1 ist hier 1 :-)
005DB646 8D55F8           lea edx,[ebp-$08] // out s1
005DB649 8B45F0           mov eax,[ebp-$10] // in i
005DB64C E85B61E4FF      call IntToStr

Unit2.pas.33: s2 := I.ToString; // der Referenzzähler von s2 ist hier 2 :-(
005DB67C 8D55E8           lea edx,[ebp-$18] // out intern_s3 (intern generierte StringVariable)
005DB67F 8B45F0           mov eax,[ebp-$10] // in i
005DB682 E82561E4FF      call IntToStr
005DB687 8D45F4           lea eax,[ebp-$0c] // out s2
005DB68A 8B55E8           mov edx,[ebp-$18] // in intern_s3
005DB68D E886E0E2FF      call @UStrLAsg
Aber nein, das ergibt kein Speicherleck, denn am Ende der Prozedur (im end; ) werden alle 3 String-Variablen freigegeben.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu ( 7. Nov 2014 um 19:19 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Kraisel
Kraisel

Registriert seit: 19. Mär 2012
Ort: Bochum-Linden
64 Beiträge
 
Delphi 12 Athens
 
#3

AW: MemoryLeaks mit s := I.ToString

  Alt 7. Nov 2014, 21:33
Meine Pointermystik war nur für diese Tests ein Ersatz, um nicht ständig in der CPU-Ansicht die Speicherbereiche einzutippen! Ich wollte sicher sein, dass wirklich der Speicher so aussieht. Deshalb habe ich keine Methoden aus dem System genommen. Wird ansonsten nicht genutzt.

Des Rätsels Lösung ist dann wohl, dass in einer Fibermethode das "end" ja nie erreicht wird, und somit die Aufräumarbeiten nicht erledigt werden. Das Aufräumen lokaler dynamischer Variablen wird vor der Fiberumschaltung per Finalize erledigt. Und hier gibt es dann wohl Probleme mit der zusätzlichen String - Referenz. Aber OK, im Moment klingt zumindest alles wieder logisch.

Danke.
Peter Kaisler
Das einzig Komplizierte ist zu begreifen wie einfach es ist.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#4

AW: MemoryLeaks mit s := I.ToString

  Alt 7. Nov 2014, 23:47
Fibers und Windows? Soweit ich mich erinnere hat Microsoft die nur sehr rudimentär implementiert als Gegenstück zu den Fibers unter Unix. Und es wird empfohlen unter Windows stattdessen Threads zu nutzen. oder hat sich da jetzt was geändert?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Kraisel
Kraisel

Registriert seit: 19. Mär 2012
Ort: Bochum-Linden
64 Beiträge
 
Delphi 12 Athens
 
#5

AW: MemoryLeaks mit s := I.ToString

  Alt 8. Nov 2014, 01:43
Threads sind ein präemptives Multitasking. Fiber ist ein kooperatives Multitasking und läuft in EINEM Thread. Die Umschaltung der Fiber kostet keine Verwaltung (wenige ns) und die einzelnen Fiber müssen auch nicht gegeneinander verriegelt werden. Der gesamte Betriebssystem Overhead ist dadurch weg. Das hat für viele technische Probleme enorme Vorteile.

Ich automatisiere z.B. riesige Prüfstände für Verdichter bis 500kW mit vielen Aggregaten, hunderten von analogen und digitalen IOs, die alle ihre eigene Logik haben, aber trotzdem auf eine Hardware (meist Interbus und viele Schaltschränke) zugreifen. Mit Threads würde das System nur noch sich selber verwalten, und die gegenseitige Verriegelung und gleichzeitige Synchronisierung würde einem Stehhaare bescheren. Mit Fiber oder ähnlichen Techniken kann man die einzelnen Aggregate sehr komfortabel unabhängig voneinander programmieren, und alles ist wahnsinnig schnell. Und es gibt auch keine Deadlocks.

Echte Parallelität (Threads) machen nur dann Sinn, wenn durch den Einsatz mehrerer CPU-Core ein deutlicher Performancegewinn erzielt werden kann. Wenn es aber einen Flaschenhals gibt, (bei mir z.B. die Synchronisation mit der Hardware alle paar ms) ist eine kooperative Parallelität auf einem Core ohne Overhead wesentlich schneller.

Viele nehmen dazu eine SoftSPS, aber diese Art der Programmierung empfinde ich als komplett veraltet und auch sehr umständlich. Das alte Step5 oder auch die S7 habe ich schon vor über 20 Jahren beisete gelegt, und bin froh, mit Pascal sauberen und lesbaren Code für angewandte Prozessautomation zu bauen.
Peter Kaisler
Das einzig Komplizierte ist zu begreifen wie einfach es ist.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.308 Beiträge
 
Delphi 12 Athens
 
#6

AW: MemoryLeaks mit s := I.ToString

  Alt 8. Nov 2014, 11:35
Mehrere in Fibern ausgeführte Prozeduren müssten doch langsamer sein, als einfach mehrere Prozeduren in einem Thread nacheinander aufzurufen?

Der einzige Vorteil, den ich da seh, daß man den Fiber einfach mal so mittendrin anhalten könnte, aber einen Thread kann man ja genauso gut anhalten. (auch wenn man das eigentlich nicht machen sollte, was dabei allerdings auch für die Fiber gilt)

Nachteil, man zerschießt sich die automatische Speicherverwaltung.
Das fängt im Delphi schon bei den Strings, dyn. Arrays, Interfaces und Variants an, und geht im NextGen bei allen Objekten weiter. (hatte hier gestern gelesen, daß man versucht Fiber auch in anderen Platformen haben will)



Die winzige Lösung, welche ich sehe, daß sich Fiber nicht einfach so selber beenden dürfen.
Man könnte die aufgerufenen Prozeduren in eine leere Dummy-Procedure legen, wo nur der Aufruf der Funktion drin ist und sonst nichts, was irgendwie Speicher oder die Exceptionbehandlung beinhalten sollte (außer eventuell genau an Fiber angepasste Funktionen). Also genauso wie beim TThread.Execute.



PS: Sobald auch nur eine lokale String-Variable in einer Funktion deklariert wurde, egal ob manuell oder durch soeine interne Variable, wird auch noch ein Try-Finally dort eingebaut.

Dieser Code
Delphi-Quellcode:
procedure Test;
var
  s1,s2: String;
  i: Integer;
begin
  i := 123;
  s1 := IntToStr(I);
  GetDynVarPrms(s1);
  s2 := I.ToString;
  GetDynVarPrms(s2);
end;
wird, so in etwa, in Folgendes übersetzt (grob in Pure-Pascal übersetzt)
Delphi-Quellcode:
procedure Test;
var
  intern : record
    s1, s2, intern_s3: String;
    i: Integer;
  end;
begin
  {$REGION 'begin'}
  PushVariablesToStack(intern); // inkl. Initialize(intern); , indem die String-Variablen mit 0 beschrieben werden
  try
    with intern do begin
  {$ENDREGION}
      i := 123;
      IntToStr(I, s1); // procedure IntToStr(i: Integer; var Result: string);
      GetDynVarPrms(s1);
      TIntegerHelper.ToString(i, intern_s3); //intern_s3 := I.ToString; // procedure TIntegerHelper.ToString(Value: Integer; var Result: string); inline;
      UStrLAsg(s2, intern_s3); //s2 := intern_s3;
      GetDynVarPrms(s2);
      // und hier hat dein Fiber alles weggeknallt
  {$REGION 'end'}
    end;
  finally
    Finalize(intern);
  end;
  PopVariablesFromStack(intern);
  {$ENDREGION}
end;
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu ( 8. Nov 2014 um 11:54 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:38 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 by Thomas Breitkreuz