AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Wann werden Exception-Objekte freigegeben?
Thema durchsuchen
Ansicht
Themen-Optionen

Wann werden Exception-Objekte freigegeben?

Ein Thema von himitsu · begonnen am 8. Sep 2009 · letzter Beitrag vom 9. Sep 2009
Antwort Antwort
Benutzerbild von himitsu
himitsu

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

Wann werden Exception-Objekte freigegeben?

  Alt 8. Sep 2009, 21:33
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:
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;
Aufgerufen wurde/wird es bei mir so:
Delphi-Quellcode:
Try
  ...
Except
  On E: Exception do TXHelper.HandleException(E, _OnException, Self);
End;
Ich konnte diesen Code bis jetzt noch nicht testen (da das Gesamtprojekt noch nicht wieder lauffähig ist)

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;
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

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

Re: Wann werden Exception-Objekte freigegeben?

  Alt 8. Sep 2009, 22:19
Gerade ausprobiert:
Delphi-Quellcode:
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;
Reihenfolge: OnExcept -> Destroy -> End
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
 
#3

Re: Wann werden Exception-Objekte freigegeben?

  Alt 8. Sep 2009, 22:44
Auf die Idee, es so leicht zu prüfen war ich jetzt garnicht gekommen

Hatte nur keine große Lust es zu debuggen und hatte die Hoffnung es weiß schon einer

Hab es gleich nochmal rekursiv probiert.
Delphi-Quellcode:
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;
Es wird also immer gleich nach seiner letzen Verwendung freigegeben.

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.
Delphi-Quellcode:
{Unit System}
function ExceptObject: TObject;
begin
  if RaiseListPtr <> nil then
    Result := PRaiseFrame(RaiseListPtr)^.ExceptObject
  else
    Result := nil;
end;
$2B or not $2B
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: Wann werden Exception-Objekte freigegeben?

  Alt 9. Sep 2009, 20:31
Himitsu, ich kann das gerade wirklich nicht glauben. Ich hätte gewettet, dass du Delphi-Referenz durchsuchenAcquireExceptionObject kennst. Bezüglich Freigabe der Exception ohne genannte Funktion schaue man in System.pas:
Delphi-Quellcode:
//_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
Sobald eine Exception also einen Except-Block verlässt (Reraise offensichtlich ausgenommen), wird die alte Exception freigegeben, AcquireExceptionObject natürlich ausgenommen.
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;
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: Wann werden Exception-Objekte freigegeben?

  Alt 9. Sep 2009, 20:57
Nee, das hat sich über die Jahre erfolgreich vor mir versteckt

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:
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;
und aufrufen tu ich's dann etwa so
Delphi-Quellcode:
Procedure TXMLFile.SetLineFeed(Const Value: UnicodeString);
  Begin
    If ... Then
      Raise EXMLException.Create(Self.ClassType, 'LineFeed', @SInvalidValue, Value);
    _LineFeed := Value;
  End;
$2B or not $2B
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: Wann werden Exception-Objekte freigegeben?

  Alt 9. Sep 2009, 21:11
Warum holst du dir nicht mit AcquireExceptionObject die alte Exception und speicherst sie als Feld in der neuen Exception?
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: Wann werden Exception-Objekte freigegeben?

  Alt 9. Sep 2009, 21:37
Dann müßte ich es ja schonwieder umbauen und mir vorher noch überlegen, wie ich die SystemErrorMessages (GetLastError) dort mit unterbekomm
$2B or not $2B
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: Wann werden Exception-Objekte freigegeben?

  Alt 9. Sep 2009, 21:38
Das eine schließt das andere nicht aus. Ich finde es einfach ganz nett, noch ein InnerException-Objekt zu haben. Freigabe nicht vergessen.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: Wann werden Exception-Objekte freigegeben?

  Alt 9. Sep 2009, 21:44
Zitat von Apollonius:
Das eine schließt das andere nicht aus. Ich finde es einfach ganz nett, noch ein InnerException-Objekt zu haben. Freigabe nicht vergessen.
Am Ende hab ich dann eine Exception in einer Exception in einer Exception.
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.
$2B or not $2B
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#10

Re: Wann werden Exception-Objekte freigegeben?

  Alt 9. Sep 2009, 21:58
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.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  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 16:21 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