AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi EOutOfResources erzeugt Speicherleck
Thema durchsuchen
Ansicht
Themen-Optionen

EOutOfResources erzeugt Speicherleck

Ein Thema von Schorschi5566 · begonnen am 5. Dez 2010 · letzter Beitrag vom 6. Dez 2010
Antwort Antwort
Seite 2 von 3     12 3      
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#11

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 16:59
Hallo littleDave,

vielen Dank für die Info. Darauf lässt sich aufbauen.


Grüße,
Schorsch
Uwe
"Real programmers can write assembly code in any language." - Larry Wall
Delphi programming rocks
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer
Online

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 17:35
Wenn 30 Threads versuchen jeweils eine Grafik mit 5000x5000 Punkten in den Speicher zu laden, bekommt man die Meldung recht schnell.
Das Problem ist das jede Grafik ca. 100 MB an durchgehenden Adressraum benötigen (bei 32-Bit Farbtiefe). Da dein Adressraum (mit entsprechender Linker-Option) maximal 3 GB umfasst, aber Windows und diverse Anwendungen DLL's in deinen Adressraum "injezieren" ist 30*100MB eher schon Glück wenn es nicht permanent kracht.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#13

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 18:03
Das ist ja gar nicht das Problem. Klar kracht das (fast) permanent, wenn viele so große Grafiken verarbeitet werden.

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.
Uwe
"Real programmers can write assembly code in any language." - Larry Wall
Delphi programming rocks

Geändert von Schorschi5566 ( 5. Dez 2010 um 18:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

Registriert seit: 27. Apr 2006
Ort: München
556 Beiträge
 
Delphi 7 Professional
 
#14

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 18:59
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:
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;
Das ganze muss natürlich etwas angepasst werden, falls in neueren Delphi-Versionen die Klasse "EHeapException" noch weitere Variablen hat.
Jabber: littleDave@jabber.org
in case of 1 is 0 do external raise while in public class of object array else repeat until 1 is 0
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 20:26
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. Delphi-Referenz durchsuchenOutOfMemoryError auf, welches das schon vorhandene globale Objekt nutzt.


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.
$2B or not $2B

Geändert von himitsu ( 5. Dez 2010 um 20:33 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#16

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 20:36
@himitsu das wurde doch schon hier erwähnt
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 21:24
Ich meinte von BorCodEmba entdeckt und behoben
$2B or not $2B
  Mit Zitat antworten Zitat
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#18

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 22:30
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.
Uwe
"Real programmers can write assembly code in any language." - Larry Wall
Delphi programming rocks
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

Registriert seit: 27. Apr 2006
Ort: München
556 Beiträge
 
Delphi 7 Professional
 
#19

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 22:41
Ah, du hast Delphi 2010, da musst du es so machen:

Delphi-Quellcode:
    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.)
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.
Jabber: littleDave@jabber.org
in case of 1 is 0 do external raise while in public class of object array else repeat until 1 is 0
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: EOutOfResources erzeugt Speicherleck

  Alt 5. Dez 2010, 22:46
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.
$2B or not $2B

Geändert von himitsu ( 5. Dez 2010 um 22:53 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 17:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz