Frage zum Exception Handling

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Frage zum Exception Handling

Beitrag von Kay »

Hallo zusammen,

ich hätte folgende Frage zum Exception Handling:
Wenn ich aus irgendeinem Grund eine Exception werfe, wird ja ein neues Exception-Objekt erzeugt. Ich frage mich allerdings jetzt, wann dieses Objekt wieder freigegeben wird. Muss ich das selber freigeben oder gibt es für Exceptions eine Art GC?
Vorstellbar wäre folgender Beispielcode:

Code: Alles auswählen

type
  EMyException = class(Exception);
 
function TRechteck.BerechneFlaeche(A, B: Integer): Integer;
begin
  If (A < 0) or (B < 0) raise EMyException.Create('blabla');
  Result := A * B;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    Rechteck.BerechneFlaeche(10, -1);
  except
    On E: EMyException Do ShowMessage(E.Message);
  end;
end;
Die Sinnhaftigkeit der Implementierung sei mal dahingestellt - soll nur ein Beispiel sein. Mir geht's lediglich darum, ob das Exception-Objekt automatisch freigegeben wird oder ob ich im except-Block die Methode Free() aufrufen muss (oder ähnliches).

Viele Grüße
Kay

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Frage zum Exception Handling

Beitrag von theo »

Gute Frage. Ich kann nur sagen, dass ich noch nie gesehen habe, dass da was im Code freigegeben wird.
Es gibt ja auch keine Instanzvariable, à la: raise InstVar:=EMyException.Create('blabla');

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Frage zum Exception Handling

Beitrag von m.fuchs »

Probieren wir doch mal ein bisschen herum. Dazu hab ich dein Programm ein kleines bisschen angepasst:

Code: Alles auswählen

program test;
{$MODE ObjFpc}
{$H+}
 
uses
  heaptrc, classes, sysutils;
 
type
  EMyException = class(Exception);
 
function BerechneFlaeche(A, B: Integer): Integer;
begin
  If (A < 0) or (B < 0) then
    raise EMyException.Create('blabla');
  Result := A * B;
end;
 
begin
  try
    WriteLn(BerechneFlaeche(10, 2));
    WriteLn(BerechneFlaeche(10, -1));
  except
    On E: EMyException Do begin
      WriteLn(E.Message);
      //E.Free;
    end;
  end;
  WriteLn('Bye.');
end.
Wenn wir nun das ganze kompilieren und durchlaufen lassen, sagt uns die Ausgabe folgendes:

Code: Alles auswählen

20
blabla
Bye.
Heap dump by heaptrc unit
21 memory blocks allocated : 1189/1224
21 memory blocks freed     : 1189/1224
0 unfreed memory blocks : 0
True heap size : 360448
True free heap : 360448
Wunderbar, kein reservierter Speicher, der nicht wieder freigegeben wird. Könnte man die gefangene Exception freigeben? Dazu entfernen wir die Auskommentierung aus der Zeile

Code: Alles auswählen

//E.Free;
Und die Ausgabe des neuen Kompilats:

Code: Alles auswählen

20
blabla
An unhandled exception occurred at $0805475F :
EAccessViolation : Access violation
  $0805475F
 
Heap dump by heaptrc unit
25 memory blocks allocated : 1297/1344
23 memory blocks freed     : 1261/1304
2 unfreed memory blocks : 36
True heap size : 425984
True free heap : 425808
Should be : 425832
Call trace for block $B7F4F048 size 24
  $080555F0
  $080557BD
  $08089AE0
  $080588A7
  $08094D87
Call trace for block $B7F5F3B8 size 12
  $08054852
  $0808990E
  $080588A7
  $08094D87
Und siehe da, man sollte die Exception wohl nicht versuchen freizugeben.

Noch eine Schlussanmerkung:
theo hat geschrieben:Es gibt ja auch keine Instanzvariable, à la: raise InstVar:=EMyException.Create('blabla');
Doch die gibt es, allerdings nicht beim Werfen sondern beim Fangen der Exception:

Code: Alles auswählen

On E: EMyException Do begin
E ist damit die Instanzvariable der gefangenen Exception.

hth
Michael
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Frage zum Exception Handling

Beitrag von m.fuchs »

Um dem praktischen Teil noch etwas Theorie folgen zu lassen, hier noch ein Auszug aus der Free Pascal Dokumentation:

Code: Alles auswählen

If, on the other hand, the exception was caught, then the exception object is destroyed at the end of the exception handling block, before program flow continues. The exception is destroyed through a call to the object’s Destroy destructor.
Micha
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Re: Frage zum Exception Handling

Beitrag von Kay »

Alles klar, da läuft also dann eine Art GC durch. Sehr gut, dann brauche ich mich also darum nicht zu kümmern.
Vielen Dank für die Antworten und viele Grüße
Kay

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Frage zum Exception Handling

Beitrag von m.fuchs »

Naja, als Garbage Collection würde ich das nicht bezeichnen, aber ja: du musst dich um nichts kümmern.

Micha
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten