Hallo pl,
Denn das hieße ja, daß man spätestens beim Erstellen der 2. Exceptioninstanz die 1. Exception ignoriert hat!
Wer Exceptions nicht fängt, dem wird von der Runtime standrechtlich der Thread gecancelled. Wer sie fängt und ignoriert, ist selbst schuld.
Eine Exception-Instanz ist eine Nachrichtenkapsel. Sie wird gefüllt, fallen gelassen (throw) und fällt dann solange am Callstack entlang bis jemand mit einem Netz bereit steht. Wenn er sich zuständig fühlt (catch mit ClassName), fängt er sie weg, macht die Kapsel auf und liest die Nachricht. Danach kann er sie in den Müll werfen (vom Garbage Collector deallocieren lassen) oder die Kapsel wieder zumachen und fallen lassen (rethrow, Stacktrace bleibt). Statt dessen kann er die Kapsel auch in eine neue Kapsel stecken, einen Zettel dazulegen und die größere Kapsel rauswerfen (InnerException). Fühlt sich keiner zuständig, fällt sie durch bis auf die Grundplatte (Laufzeitumgebung), löst Alarm aus und beendet das Programm.
Entscheidend ist aber: Wenn die Exception nicht weiter geworfen wird, wird das Objekt vom Exceptionhandling deallociert. Das geschieht in den meisten Sprachen automatisch. Du kannst es für eine neue Exception gar nicht verwenden, bei der nächsten Exception wird ein neues Objekt erzeugt.
In Perl ist das - wenn ich das richtig verstehe - anders. Um Exceptions zu fangen brauchst Du einen eval-Block, und der baut gnadenlos einen Trichter namens $@ auf, in dem jede Exception landet. Eine Exception nicht zu fangen ist überhaupt nicht möglich. Du kannst sie nur weiterwerfen. Und ob Du das Exception-Objekt deallocierst, bleibt Dir überlassen. Wenn nicht, liegt es in $@ herum bis die nächste Exception die Referenz überschreibt und dem Garbage Collector freie Hand gibt.
Hier ist wohl der Haupt-Unterschied zwischen Perl und vielen anderen Sprachen: In Perl musst Du zugreifen, in C# oder PHP kannst Du die Exception vorbeirauschen lassen.
In PHP oder C# ist es von der Gültigkeit her so:
try {
callFunc();
}
catch (InvalidArgumentException x) {
// behandeln
}
function callFunc() {
throw new InvalidArgumentException("Ätsch");
}
Das Exception-Objekt existiert in callFunc() nur temporär. Es wird erzeugt, geworfen und keine Referenz darauf gespeichert. Man KÖNNTE anderes tun, man KÖNNTE ein Exception-Objekt an anderer Stelle speichern oder in eine Closure stecken, aber sowas tut man nicht. Man belässt die Referenz schön beim Auslöser auf dem Stack.
Nachdem die Exception geworfen wurde, hält das Exception-Handling die Referenz auf das Exception-Objekt und räumt solange Stackframes ab, bis ein passender catch dazwischen kommt. Jetzt wird das Exception-Objekt an den Parameter von catch zugewiesen, und der hat nun die Verantwortung dafür. Das Exception-Handling gibt seine Referenz frei.
Was nach Ende des Catch-Block passiert hängt von der Sprache ab. C# hat ein striktes Blockkonzept, wird der Catch-Block verlassen ist das Objekt referenzfrei und kann collected werden. In PHP nicht, da lebt es nach dem catch noch und wird - sofern man es nicht speichert - am Ende der Funktion dem GC zum Fraße vorgeworfen. Ist man in keiner Funktion, lebt es bis zum Script-Ende...
Rolf
sumpsi - posui - clusi