Wie weiß der Compiler, welcher catch-Block verwendet werden soll?

8

Angenommen, ich habe die folgenden zwei Dateien, main.cpp :

%Vor%

und foo.cpp :

%Vor%

Wenn ich nun jede dieser Dateien separat kompiliere, die resultierenden Objektdateien verknüpfe und die resultierende ausführbare Datei ausführe, bekomme ich das erwartete Ergebnis:

%Vor%

Und das verwirrt mich! Die Klasse A hat keine virtuellen Methoden. Daher ist es nicht polymorph und seine Instanzen sollten zur Laufzeit keine Typinformationen enthalten. Die main.o -Objektdatei weiß nicht, was geworfen wird, da das eigentliche Werfen in foo() stattfindet, dessen Körper in einer separaten Kompilierungseinheit definiert ist. Die foo.o -Objektdatei enthält mehr Informationen, ist sich aber ebenso keiner Fanganweisungen und der erwarteten Arten gefangener Ausnahmen bewusst.

Kurz gesagt: Ich sehe nicht, wie die zwei separat kompilierten und dann verknüpften Quelldateien die obige Eingabe erzeugen können, ohne dass einige Laufzeit-Informationen verfügbar sind. Keine Datei, die separat kompiliert wird, sollte genügend Informationen haben, um den richtigen catch-Block zu nehmen.

    
Witiko 24.11.2016, 22:28
quelle

2 Antworten

5

Dies ist natürlich vollständig kompilerabhängig.

Die Einschränkungen für alle Compiler sind:

  • Der Typ der Ausnahmebedingung ist bekannt, wenn Sie einen Wurf ausführen (entweder zur Kompilierzeit oder zur Laufzeit, wenn Sie ein polymorphes Objekt werfen).
  • die anwendbaren catch-Blöcke (ihre können mehrere sein) und ihre Typen hängen vom Ausführungspfad ab.

Dies bedeutet, dass der Typ zur Laufzeit erkannt werden muss, auch wenn das Ausnahmeobjekt nicht plymorph ist.

Ein einfacher Weg, dies zu erreichen, besteht darin, einen Zeiger auf ein typeinfo -Objekt zusammen mit dem geworfenen Objekt selbst zu übergeben. Dies ist der von GCC verwendete Ansatz: siehe Online-Code , hier ein Auszug aus dem Werfen in foo() für die Bequemlichkeit:

%Vor%     
Christophe 24.11.2016, 22:54
quelle
2

Es handelt sich um eine Kombination aus RTTI (Informationen zum Laufzeittyp) und den implementierungsspezifischen codierten Datentypen, die zum Vergleichen von Typen generiert werden, wenn ermittelt werden soll, welcher catch-Block was erreicht.

Wenn Sie jedoch zwei Typen mit dem Wert face vergleichen, erhalten Sie möglicherweise nicht das richtige Ergebnis (wie in Ihrem Fall mit Basis- und abgeleiteten Klassen). Im Falle von Windows & amp; SEH, eine spezielle zusätzliche erweiterte Typinformationsstruktur ( etype_info oder etwas ähnliches) existiert, die alle Klassen in der Hierarchie enthält, die durchlaufen werden müssen, um eine potentielle Übereinstimmung zu bestimmen (da eine Basisklasse eine einschränkende Ansicht in das abgeleitete sein kann) Klasse). Wenn nach dem Durchlaufen einer Übereinstimmung gefunden wird, wird catch-Block aufgerufen.

Zusatz

Ausnahmebehandlung erfordert spezielle Laufzeitunterstützung, die vom Betriebssystem bereitgestellt wird, und daher ist die Implementierung definiert (z. B. strukturierte Ausnahmebehandlung in Windows), solange das Endergebnis dem Standard entspricht.

Oben ist der Windows-artige Kern davon.

    
Benjamin Sisko 24.11.2016 23:03
quelle