![]() |
AW: EOutOfResources erzeugt Speicherleck
Hallo littleDave,
vielen Dank für die Info. Darauf lässt sich aufbauen. :) Grüße, Schorsch |
AW: EOutOfResources erzeugt Speicherleck
Zitat:
|
AW: EOutOfResources erzeugt Speicherleck
Das ist ja gar nicht das Problem. Klar kracht das (fast) permanent, wenn viele so große Grafiken verarbeitet werden. :D
Aber der Mechanismus bei Speichermangel die Threads zu killen und sie langsam wieder "auferstehen" zu lassen funktioniert ja. Es sind nicht nur derart große Grafiken, sondern auch viele mit kleineren Formaten. Da wäre es einfach doof, die Threads nicht wieder zu starten. Natürlich nicht alle auf einmal. Die Leckage scheint wohl eher daher zu kommen, dass EOutOfResources irgendwo direkt geraised wird, was ja, laut Hilfe, für EHeapExceptions nicht erlaubt ist. Dabei entsteht pro Exception offenbar eine neue Instanz von EOutOfResources, was eigentlich nicht sein soll. Freigegeben wird aber nur die Urinstanz von EOutOfResources. Mein Code feuert keine EOutOfResources, also muss es wohl TJpgImage, TBitmap oder TBitMap32 sein. In meiner Exceptionbehandlung habe ich ja wohl kaum eine Chance, das zu beheben. Oder doch? Bleibt die Frage, wie man korrekt auf EOutOfResources reagieren kann ohne eine Speicherleck zu erzeugen. |
AW: EOutOfResources erzeugt Speicherleck
Soweit ich das gesehen habe, ist das ganze (in Delphi 7) nicht sauber umgesetzt, da es - nicht wie bei EOutOfMemory - keine Methode gibt, die das gleiche für die EOutOfResources-Exceptions macht (habe keine gefunden).
Erstmal grundlegend: EHeapException hat eine private Boolean-Variable namens "AllowFree". Wenn diese True ist, wird die Instanz wirklich aus dem Speicher gelöscht, ansonsten nicht. Zur Prüfung dieser Variable überschreibt EHeapException die virtuelle TObject-Methode "FreeInstance" und baut dort die Prüfung ein (siehe SysUtils.pas -> EHeapException.FreeInstance). Um das zu umgehen, hab ich eben eine Quick-and-Dirty-Lösung zusammengebaut
Delphi-Quellcode:
Das ganze muss natürlich etwas angepasst werden, falls in neueren Delphi-Versionen die Klasse "EHeapException" noch weitere Variablen hat.
procedure TForm1.Button1Click(Sender: TObject);
var delta: cardinal; begin try raise EOutOfResources.Create('Out of resources'); except on e: EOutOfResources do begin delta := cardinal(EHeapException.ClassParent.InstanceSize); // den Offset zur Boolean-Variable auslesen PBoolean(cardinal(e) + delta)^ := True; // "AllowFree" auf "True" setzen (Offset + Instance-Pointer = Heap Pointer) end; // <-- hier wird die Exception dann automatisch freigegeben (siehe auch: AcquireExceptionObject, etc.) end; end; |
AW: EOutOfResources erzeugt Speicherleck
EHeapException und Nachfahren, wie EOutOfMemory und EOutOfResources ruft man auch nicht direkt via Raise auf.
Diese sind ja nötig, wenn entsprechende Resourcen schon aufgebraucht sind und man diese Exceptions eventuell garnicht mehr erzeugen kann. Für EOutOfMemory ruft man z.B. ![]() EOutOfResources also direkt aufzurufen wäre der falsche Weg, was demnach für einen fehlerhafte Nutzung in Delphi spricht. Schon interessant, daß dieser Designfehler bis jetzt nicht so sehr aufgefallen ist. :shock: |
AW: EOutOfResources erzeugt Speicherleck
@himitsu das wurde doch schon
![]() |
AW: EOutOfResources erzeugt Speicherleck
Ich meinte von BorCodEmba entdeckt und behoben :angel:
|
AW: EOutOfResources erzeugt Speicherleck
Hallo zusammen,
nochmals vielen Dank für die rege Beteiligung. :) @littleDave: Klingt plausibel, funktioniert aber irgendwie nicht. Der Inhalt von PBoolean(cardinal(e) + delta)^ ist zwar False und wird dementsprechend auf True gesetzt, aber die Meldung vom Speichermanager (der bei Delphi2010 ja wohl FastMem ist) bleibt die gleiche. @himitsu: Es geht ja nicht darum, dass ich die Exception auslösen, sondern dass ich darauf reagieren will. Mache ich ja auch, nur bleibt dabei eben die Exception übrig. :stupid: |
AW: EOutOfResources erzeugt Speicherleck
Ah, du hast Delphi 2010, da musst du es so machen:
Delphi-Quellcode:
In Delphi 2010 wird an das Ende der Klasseninstanz noch eine TMonitor-Referenz gespeichert. Daher muss der Pointer auf diese Referenz vom Offset noch abgezogen werden.
on e: EOutOfResources do
begin delta := cardinal(EHeapException.ClassParent.InstanceSize) - SizeOf(Pointer); // den Offset zur Boolean-Variable auslesen PBoolean(cardinal(e) + delta)^ := True; // "AllowFree" auf "True" setzen (Offset + Instance-Pointer = Heap Pointer) end; // <-- hier wird die Exception dann automatisch freigegeben (siehe auch: AcquireExceptionObject, etc.) |
AW: EOutOfResources erzeugt Speicherleck
Ich sag ja, ist ein Fehler in Delphi.
Diese Exception dürfte erst garnicht ständig neu erzeugt werden ... wie es richtig geht, sieht man an EOutOfMemory. Aber man kann es eh nicht ordentlich implementieren, da AllowFree privat ist und somit in anderen Units nicht nutzbar ist. (sowas gehört in protected) Fazit: Dieses Singleton ist fehlerhaft implementiert und falsch verwendet. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:30 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