![]() |
Wann werden Exception-Objekte freigegeben?
Mal so rein aus Interesse. (hab meinen Code nun doch anders gestaltet)
Wann werden diese Objekte denn eigentlich freigegeben? Bis grad eben hatte ich noch Folgendes verbaut:
Delphi-Quellcode:
Aufgerufen wurde/wird es bei mir so:
Class Procedure TXHelper.HandleException(E: Exception; Proc: TXMLExceptionEvent; Owner: TObject);
Var B: Boolean; Begin B := False; Try If Assigned(Proc) Then Proc(Owner, E, B); Except On E2: Exception do Begin E := E2; B := True; End; End; If B Then ShowException(E, nil); End;
Delphi-Quellcode:
Ich konnte diesen Code bis jetzt noch nicht testen (da das Gesamtprojekt noch nicht wieder lauffähig ist)
Try
... Except On E: Exception do TXHelper.HandleException(E, _OnException, Self); End; Wäre es da eventuell zu Problemen gekommen? Also E ist ja noch innerhalb seiner Except-Blocks, aber E2 wäre ja außerhalb gewesen. PS: jetzt sieht mein Code so aus:
Delphi-Quellcode:
Class Procedure TXHelper.HandleException(E: Exception; Proc: TXMLExceptionEvent; Owner: TObject);
Var B: Boolean; Begin Try B := False; If Assigned(Proc) Then Proc(OwnerE, B); If B Then ShowException(E, nil); Except On E2: Exception do ShowException(E2, nil); End; End; |
Re: Wann werden Exception-Objekte freigegeben?
Gerade ausprobiert:
Delphi-Quellcode:
Reihenfolge: OnExcept -> Destroy -> End
type
EMyException = class(Exception) public destructor Destroy; override; end; destructor EMyException.Destroy; begin ShowMessage('Destroy'); inherited; end; procedure TForm1.Button1Click(Sender: TObject); begin try raise EMyException.Create('Test'); except on e:Exception do ShowMessage('OnExcept'); end; ShowMessage('End'); end; |
Re: Wann werden Exception-Objekte freigegeben?
Auf die Idee, es so leicht zu prüfen war ich jetzt garnicht gekommen :oops:
Hatte nur keine große Lust es zu debuggen und hatte die Hoffnung es weiß schon einer :nerd: Hab es gleich nochmal rekursiv probiert.
Delphi-Quellcode:
Es wird also immer gleich nach seiner letzen Verwendung freigegeben.
destructor EMyException.Destroy;
begin ShowMessage('Destroy: ' + Message); inherited; end; procedure TForm1.Button1Click(Sender: TObject); begin try try raise EMyException.Create('Test 1'); except on E: Exception do begin ShowMessage('OnExcept: ' + E.Message); raise EMyException.Create('Test 2'); end; end; except on E: Exception do ShowMessage('OnExcept: ' + E.Message); {X} end; ShowMessage('End'); end; Und hier demnach erst nach dem 2. Try-Except-Block.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin try try raise EMyException.Create('Test 1'); except on E: Exception do begin ShowMessage('OnExcept: ' + E.Message); raise; end; end; except on E: Exception do ShowMessage('OnExcept: ' + E.Message); end; ShowMessage('End'); end; Nja, es hätte ja sein können, daß bis alle Objekte mindestens bis zur letzen Except-Ebene aufgehoben werden und man somit eine Art Backtacking hätte durchführen können, um so alle nachfolgenden(vorhergehenden) Exception rauszubekommen. Also daß man z.B. an Punkt {X} auch noch von der Exception 'Test 1' hätte etwas erfahren können. Jedenfalls hätte ich hier durch das RaiseListPtr soetwas vermutet. :gruebel:
Delphi-Quellcode:
{Unit System}
function ExceptObject: TObject; begin if RaiseListPtr <> nil then Result := PRaiseFrame(RaiseListPtr)^.ExceptObject else Result := nil; end; |
Re: Wann werden Exception-Objekte freigegeben?
Himitsu, ich kann das gerade wirklich nicht glauben. Ich hätte gewettet, dass du
![]()
Delphi-Quellcode:
Sobald eine Exception also einen Except-Block verlässt (Reraise offensichtlich ausgenommen), wird die alte Exception freigegeben, AcquireExceptionObject natürlich ausgenommen.
//_HandleAnyException - selbiges in _HandleOnException
JMP EBX //zum Handler springen @@exceptFinally: JMP _HandleFinallyInternal @@destroyExcept: { we come here if an exception handler has thrown yet another exception } { we need to destroy the exception object and pop the raise list. } CALL SysInit.@GetTLS MOV ECX,[EAX].RaiseListPtr MOV EDX,[ECX].TRaiseFrame.NextRaise MOV [EAX].RaiseListPtr,EDX MOV EAX,[ECX].TRaiseFrame.ExceptObject JMP TObject.Free Die von dir angesprochene Raiselist ist in einem anderen Fall wichtig:
Delphi-Quellcode:
try
raise EFirstException.Create(''); except //die aktuelle Exception ist eine EFirstException try raise ESecondException.Create(''); except //die aktuelle Exception ist eine ESecondException end; //die ESecondException ist zerstört worden: die EFirstException ist jetzt aktuell end; |
Re: Wann werden Exception-Objekte freigegeben?
Nee, das hat sich über die Jahre erfolgreich vor mir versteckt :shock:
Hmmm, diese Art der Verschachtelung kommt bei mir recht selten vor. Aktuell sieht es bei mir so aus ... bei einem Re-Raise wird die alte Exception der Neuen im Constructor mitgegeben und die Messages werden samt Klassen- und Funktionsnamen miteinander verbunden.
Delphi-Quellcode:
und aufrufen tu ich's dann etwa so
Type EXMLException = Class(Exception)
_Info: Array of Record ErrorClass: TClass; FunctionsName: String; Message: String; End; Const MaxXMLErrStr = 200; Class Function Str(S: AnsiString; MaxLen: Integer = MaxXMLErrStr): String; Overload; Class Function Str(S: UnicodeString; MaxLen: Integer = MaxXMLErrStr): String; Overload; Constructor Create(ErrorClass: TClass; Const FunctionsName: String; ResStringRec: PResStringRec; Const Args: Array of Const; PrevException: Exception = nil; ErrorCode: LongWord = ERROR_SUCCESS); Overload; Constructor Create(ErrorClass: TClass; Const FunctionsName: String; ResStringRec: PResStringRec; Const S: UnicodeString); Overload; Constructor Create(ErrorClass: TClass; Const FunctionsName: String; ResStringRec: PResStringRec; i: Integer = 0); Overload; End; Class Function EXMLException.Str(S: AnsiString; MaxLen: Integer = MaxXMLErrStr): String; Const Width: Array[Boolean] of Byte = (2, 4); Var i: Integer; Begin If MaxLen < 0 Then Begin If Length(S) > -MaxLen Then S := Copy(S, 1, -MaxLen); End Else If Length(S) > MaxLen Then S := Copy(S, 1, MaxLen) + '...'; For i := Length(S) downto 1 do If Ord(S[i]) in [0{..9, 11, 12, 14.}..31, 34, 127, 160, 255] Then Begin Insert(AnsiString(Format('%.*x', [Width[(i < Length(S)) and (Ord(S[i + 1]) in [Ord('0')..Ord('9'), Ord('A')..Ord('F'), Ord('a')..Ord('f')])], Ord(S[i])])), S, i + 1); S[i] := '#'; End; Result := String(S); End; Class Function EXMLException.Str(S: UnicodeString; MaxLen: Integer = MaxXMLErrStr): String; Const Width: Array[Boolean] of Byte = (2, 4); Var i: Integer; Begin If MaxLen < 0 Then Begin If Length(S) > -MaxLen Then S := Copy(S, 1, -MaxLen); End Else If Length(S) > MaxLen Then S := Copy(S, 1, MaxLen) + '...'; For i := Length(S) downto 1 do If ((SizeOf(Char) = 1) and (Ord(S[i]) > 255)) or (Ord(S[i]) in [0{..9, 11, 12, 14.}..31, 34, 127, 160, 255]) Then Begin Insert(UnicodeString(Format('%.*x', [Width[(i < Length(S)) and (Ord(S[i + 1]) in [Ord('0')..Ord('9'), Ord('A')..Ord('F'), Ord('a')..Ord('f')])], Ord(S[i])])), S, i + 1); S[i] := '#'; End; Result := String(S); End; Constructor EXMLException.Create(ErrorClass: TClass; Const FunctionsName: String; ResStringRec: PResStringRec; Const Args: Array of Const; PrevException: Exception = nil; ErrorCode: LongWord = ERROR_SUCCESS); Var i: Integer; Begin If PrevException is EXMLException Then _Info := Copy(EXMLException(PrevException)._Info) Else If PrevException is Exception Then Begin SetLength(_Info, 1); _Info[0].ErrorClass := ErrorClass; _Info[0].FunctionsName := '-'; _Info[0].Message := Exception(ErrorClass).Message; End; If ErrorCode <> ERROR_SUCCESS Then Begin i := Length(_Info); SetLength(_Info, i + 1); _Info[i].ErrorClass := nil; _Info[i].FunctionsName := 'System'; _Info[i].Message := SysErrorMessage(ErrorCode); End; i := Length(_Info); SetLength(_Info, i + 1); _Info[i].ErrorClass := ErrorClass; _Info[i].FunctionsName := FunctionsName; _Info[i].Message := Format(LoadResString(ResStringRec), Args); Message := Format('[%s] ' + '%s.%s:' + sLineBreak + '%s', [ClassName, _Info[i].ErrorClass.ClassName, _Info[i].FunctionsName, _Info[i].Message]); While (i > 0) and (Length(Message) < 3000) do Begin Dec(i); Message := Format('%s' + sLineBreak + sLineBreak + '%s.%s:' + sLineBreak + '%s', [Message, _Info[i].ErrorClass.ClassName, _Info[i].FunctionsName, _Info[i].Message]); End; If Length(Message) > 3500 Then Message := Copy(Message, 1, 3497) + '...'; End; Constructor EXMLException.Create(ErrorClass: TClass; Const FunctionsName: String; ResStringRec: PResStringRec; Const S: UnicodeString); Begin Create(ErrorClass, FunctionsName, ResStringRec, [Str(S)]); End; Constructor EXMLException.Create(ErrorClass: TClass; Const FunctionsName: String; ResStringRec: PResStringRec; i: Integer = 0); Begin Create(ErrorClass, FunctionsName, ResStringRec, [i]); End;
Delphi-Quellcode:
Procedure TXMLFile.SetLineFeed(Const Value: UnicodeString);
Begin If ... Then Raise EXMLException.Create(Self.ClassType, 'LineFeed', @SInvalidValue, Value); _LineFeed := Value; End; |
Re: Wann werden Exception-Objekte freigegeben?
Warum holst du dir nicht mit AcquireExceptionObject die alte Exception und speicherst sie als Feld in der neuen Exception?
|
Re: Wann werden Exception-Objekte freigegeben?
Dann müßte ich es ja schonwieder umbauen und mir vorher noch überlegen, wie ich die SystemErrorMessages (GetLastError) dort mit unterbekomm
|
Re: Wann werden Exception-Objekte freigegeben?
Das eine schließt das andere nicht aus. Ich finde es einfach ganz nett, noch ein InnerException-Objekt zu haben. Freigabe nicht vergessen.
|
Re: Wann werden Exception-Objekte freigegeben?
Zitat:
Im Grunde reichen mir aber die Texte und Namen, so daß ich mir jetzt nicht unbedingt alle Exceptions aufheben muß. Wenn die aber eh aufgehoben würden, dann hätte ich mir die Texte und Namen jedesmal dort rausgeholt. Also ich wüßte jetzt keinen Grund mir die extra selber noch aufzuheben. :gruebel: |
Re: Wann werden Exception-Objekte freigegeben?
Da ist wohl der .NET-Gaul mit mir durchgegangen. Da in Delphi der Callstack nicht im Exception-Objekt gespeichert wird, gibt es keinen Grund zur Aufbewahrung, das stimmt.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:50 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