![]() |
Delphi-Version: 10 Seattle
AcquireExceptionObject() / ReleaseExceptionObject()
Ich bin jetzt ein bisschen baff :shock:
Wenn ich möchte dass eine Exception über ihren
Delphi-Quellcode:
-Block hinaus lebt gibt es zwei Routinen
try..except
![]() ![]() Schaut man in den interface-Teil von System.pas: Zitat:
Schaut man in den implementation-Teil dann gibt es
Delphi-Quellcode:
zwei mal:
ReleaseExceptionObject()
Delphi-Quellcode:
und
procedure ReleaseExceptionObject;
begin end;
Delphi-Quellcode:
Aufgerufen wird natürlich ersteres. Heißt: Nichts passiert, die Exception verbleibt auf ewig im Speicher.
procedure ReleaseExceptionObject;
asm {$IFDEF ALIGN_STACK} SUB ESP, 12 {$ENDIF ALIGN_STACK} CALL CurrentException {$IFDEF ALIGN_STACK} ADD ESP, 12 {$ENDIF ALIGN_STACK} OR EAX, EAX JE @@Error CMP [EAX].TRaisedException.RefCount, 0 JE @@Error DEC [EAX].TRaisedException.RefCount RET @@Error: { This happens if there is no exception pending, or if the reference count on a pending exception is zero. } JMP _Run0Error end; Kann mir jemand den Sinn dahinter erklären? wtf... |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Es gibt normal auch keine Referenzzählung (ARC), also was soll es da machen?
ReleaseExceptionObject ist doch eh nur dazu da, um das Exceptionobjekt vor dem except-end freigeben zu wollen. Gibt doch kaum Gründe, wozu man das unbedingt braucht. |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Da ich nicht riechen kann was intern im Programm abläuft, wie es Resourcen in einem try..except-Block verwaltet kann ich nur auf was vertrauen was in der Doku geschrieben steht und evtl. noch was im RTL-Quelltext für mich sichtbar ist.
Gründe eine Exception länger leben zu lassen kann ich haben, finde ich. Und für mich sieht es momentan völlig falsch aus - Warum sollte man die Methode mit einem leeren Gegenstück doppeln? Ist das in neueren Delphi-Versionen immer noch so? |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Zitat:
und wenn ReleaseExceptionObject nichts macht, dann lebt die Exception-Instanz halt noch ein kleines bissl länger, als gewollt. (bis zum END vom Except) Zitat:
Jupp, ist noch so. |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Zitat:
|
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Hier werden ständig so viele Exceptions ausgelöst,
wenn die nicht freigegeben würden (im END), dann würde bei uns doch auch ständig der Speicher ausgehn. :gruebel: Aktuell noch Delphi XE, aber hier sieht der Code gleich aus. |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Habe mal mit Berlin einen kleinen Test geschrieben:
Delphi-Quellcode:
Result:
procedure ttestexception.Test1;
var p : Pointer; begin try Writeln('Test 1'); raise etestexception.Create; except Writeln('Exceptblock 1'); Writeln('AcquireExceptionObject'); p := AcquireExceptionObject; ReleaseExceptionObject; end; Writeln('Leave Test1'); end; procedure ttestexception.Test2; var p : Pointer; begin try writeln; Writeln('Test 2'); raise etestexception.Create; except Writeln('Exceptblock 2'); end; Writeln('Leave Test2'); end; { EtestException } constructor EtestException.create; begin inherited create('Test'); writeln('Create EtestException '); end; destructor EtestException.Destroy; begin writeln('Free EtestException '); inherited; end;
Code:
Wird also nicht freigegeben
Test 1
Create EtestException Exceptblock 1 AcquireExceptionObject Leave Test1 Test 2 Create EtestException Exceptblock 2 Free EtestException Leave Test2 Done |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Danke für den Test.
Mein Test wäre jetzt gewesen es in einer Schleife aufzurufen und in den Task-Manager zu schauen wie sich der Speicher füllt. Das ist natürlich schlauer :thumb: |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
Hatte ich doch gesagt
* ReleaseExceptionObject macht halt nichts, wie schon richtig gesehn, aber sooooo sehr stört es jetzt nicht * aber AcquireExceptionObject funktioniert dennoch (wäre blöd, wenn nicht) Hatte das auch grade mal schnell als Test gebastelt:
Delphi-Quellcode:
type
EMyTest = class(Exception) public // TObject procedure AfterConstruction; override; procedure BeforeDestruction; override; class function NewInstance: TObject; override; procedure FreeInstance; override; //destructor Destroy; override; protected // Exception procedure RaisingException(P: PExceptionRecord); override; public // Exception constructor Create(const Msg: string); destructor Destroy; override; end; procedure EMyTest.AfterConstruction; begin //Form5.Memo1.Lines.Add('Exception.AfterConstruction'); inherited; end; procedure EMyTest.BeforeDestruction; begin //Form5.Memo1.Lines.Add('Exception.BeforeDestruction'); inherited; end; constructor EMyTest.Create(const Msg: string); begin Form5.Memo1.Lines.Add('Exception.Create ' + Msg); inherited; end; destructor EMyTest.Destroy; begin Form5.Memo1.Lines.Add('Exception.Destroy ' + Message); inherited; end; procedure EMyTest.FreeInstance; begin //Form5.Memo1.Lines.Add('Exception.FreeInstance'); inherited; end; class function EMyTest.NewInstance: TObject; begin //Form5.Memo1.Lines.Add('Exception.NewInstance'); Result := inherited; end; procedure EMyTest.RaisingException(P: PExceptionRecord); begin Form5.Memo1.Lines.Add('Exception.RaisingException'); inherited; end; procedure TForm5.FormCreate(Sender: TObject); var E: {Exception}TObject; begin {$REGION 'normal'} Memo1.Lines.Add(''); Memo1.Lines.Add('***** normal'); try Memo1.Lines.Add('raise Exception.Create()'); //raise Exception.Create('Fehlermeldung'); raise EMyTest.Create('Fehlermeldung'); Memo1.Lines.Add('nö'); except Memo1.Lines.Add('except ' + Exception(ExceptObject).Message); Memo1.Lines.Add('end'); end; Memo1.Lines.Add('finish'); {$ENDREGION} {$REGION 'release'} Memo1.Lines.Add(''); Memo1.Lines.Add('***** release'); try Memo1.Lines.Add('raise Exception.Create()'); //raise Exception.Create('Fehlermeldung'); raise EMyTest.Create('Fehlermeldung'); Memo1.Lines.Add('nö'); except Memo1.Lines.Add('except ' + Exception(ExceptObject).Message); Memo1.Lines.Add('ReleaseExceptionObject'); ReleaseExceptionObject; Memo1.Lines.Add('end'); end; Memo1.Lines.Add('finish'); {$ENDREGION} {$REGION 'acquire'} Memo1.Lines.Add(''); Memo1.Lines.Add('***** acquire'); try Memo1.Lines.Add('raise Exception.Create()'); //raise Exception.Create('Fehlermeldung'); raise EMyTest.Create('Fehlermeldung'); Memo1.Lines.Add('nö'); except Memo1.Lines.Add('except ' + Exception(ExceptObject).Message); Memo1.Lines.Add('AcquireExceptionObject'); E := AcquireExceptionObject; Memo1.Lines.Add('end'); end; Memo1.Lines.Add('E.Free'); E.Free; Memo1.Lines.Add('finish'); {$ENDREGION} {$REGION 're-raise'} Memo1.Lines.Add(''); Memo1.Lines.Add('***** re-raise'); try try Memo1.Lines.Add('raise Exception.Create()'); //raise Exception.Create('Fehlermeldung'); raise EMyTest.Create('Fehlermeldung'); Memo1.Lines.Add('nö'); except Memo1.Lines.Add('except ' + Exception(ExceptObject).Message); Memo1.Lines.Add('raise E'); raise; Memo1.Lines.Add('end'); end; Memo1.Lines.Add('finish'); except Memo1.Lines.Add('except(2) ' + Exception(ExceptObject).Message); Memo1.Lines.Add('end(2)'); end; Memo1.Lines.Add('finish(2)'); {$ENDREGION} {$REGION 'new-raise'} Memo1.Lines.Add(''); Memo1.Lines.Add('***** new-raise'); try try Memo1.Lines.Add('raise Exception.Create(1)'); //raise Exception.Create('Fehlermeldung_1'); raise EMyTest.Create('Fehlermeldung_1'); Memo1.Lines.Add('nö'); except Memo1.Lines.Add('except ' + Exception(ExceptObject).Message); Memo1.Lines.Add('raise Exception.Create(2)'); raise EMyTest.Create('Fehlermeldung_2'); Memo1.Lines.Add('end'); end; Memo1.Lines.Add('finish'); except Memo1.Lines.Add('except(2) ' + Exception(ExceptObject).Message); Memo1.Lines.Add('end(2)'); end; Memo1.Lines.Add('finish(2)'); {$ENDREGION} {$REGION 'acquire + re-raise'} Memo1.Lines.Add(''); Memo1.Lines.Add('***** acquire + re-raise'); try Memo1.Lines.Add('raise Exception.Create()'); //raise Exception.Create('Fehlermeldung'); raise EMyTest.Create('Fehlermeldung'); Memo1.Lines.Add('nö'); except Memo1.Lines.Add('except ' + Exception(ExceptObject).Message); Memo1.Lines.Add('AcquireExceptionObject'); E := AcquireExceptionObject; Memo1.Lines.Add('end'); end; try raise E; except Memo1.Lines.Add('except ' + Exception(ExceptObject).Message); Memo1.Lines.Add('end'); end; Memo1.Lines.Add('finish'); {$ENDREGION} end;
Code:
Tja, das kaputte ReleaseExceptionObject müsste ja eigentlich so aussehn, wenn es funktionieren würde:
***** normal
raise Exception.Create() Exception.Create Fehlermeldung Exception.RaisingException except Fehlermeldung end Exception.Destroy Fehlermeldung finish ***** release raise Exception.Create() Exception.Create Fehlermeldung Exception.RaisingException except Fehlermeldung ReleaseExceptionObject end Exception.Destroy Fehlermeldung finish ***** acquire raise Exception.Create() Exception.Create Fehlermeldung Exception.RaisingException except Fehlermeldung AcquireExceptionObject end E.Free Exception.Destroy Fehlermeldung finish ***** re-raise raise Exception.Create() Exception.Create Fehlermeldung Exception.RaisingException except Fehlermeldung raise E except(2) Fehlermeldung end(2) Exception.Destroy Fehlermeldung finish(2) ***** new-raise raise Exception.Create(1) Exception.Create Fehlermeldung_1 Exception.RaisingException except Fehlermeldung_1 raise Exception.Create(2) Exception.Create Fehlermeldung_2 Exception.RaisingException Exception.Destroy Fehlermeldung_1 except(2) Fehlermeldung_2 end(2) Exception.Destroy Fehlermeldung_2 finish(2) ***** acquire + re-raise raise Exception.Create() Exception.Create Fehlermeldung Exception.RaisingException except Fehlermeldung AcquireExceptionObject end Exception.RaisingException except Fehlermeldung end Exception.Destroy Fehlermeldung finish
Code:
anstatt
***** release
raise Exception.Create() Exception.Create Fehlermeldung Exception.RaisingException except Fehlermeldung ReleaseExceptionObject Exception.Destroy Fehlermeldung <<<<<<<<<<<<<<<<< end finish
Code:
...
ReleaseExceptionObject end Exception.Destroy Fehlermeldung <<<<<<<<<<<<<<<<< finish |
AW: AcquireExceptionObject() / ReleaseExceptionObject()
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05: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