Gibt es ein C ++ - Äquivalent zu Java?
try {
...
}
catch (Throwable t) {
...
}
Ich versuche, Java / jni-Code zu debuggen, der native Windows-Funktionen aufruft, und die virtuelle Maschine stürzt immer wieder ab. Der native Code scheint beim Unit-Test in Ordnung zu sein und stürzt nur ab, wenn er über jni aufgerufen wird. Ein generischer Ausnahmefangmechanismus würde sich als äußerst nützlich erweisen.
Antworten:
fängt alle C ++ - Ausnahmen ab, sollte aber als schlechtes Design angesehen werden. Sie können den neuen current_exception-Mechanismus von c ++ 11 verwenden. Wenn Sie jedoch nicht in der Lage sind, c ++ 11 (ältere Codesysteme, die neu geschrieben werden müssen) zu verwenden, müssen Sie keinen benannten Ausnahmezeiger zum Abrufen einer Nachricht oder eines Namens verwenden . Möglicherweise möchten Sie separate catch-Klauseln für die verschiedenen Ausnahmen hinzufügen, die Sie abfangen können, und nur alles unten abfangen, um eine unerwartete Ausnahme aufzuzeichnen. Z.B:
quelle
Jemand sollte hinzufügen, dass man im C ++ - Code keine "Abstürze" abfangen kann. Diese werfen keine Ausnahmen, sondern machen alles, was sie wollen. Wenn Sie sehen, dass ein Programm aufgrund einer Nullzeiger-Dereferenzierung abstürzt, führt es ein undefiniertes Verhalten aus. Es gibt keine
std::null_pointer_exception
. Der Versuch, Ausnahmen zu fangen, hilft dort nicht weiter.Nur für den Fall, dass jemand diesen Thread liest und glaubt, die Ursache für die Programmabstürze zu bekommen. Stattdessen sollte ein Debugger wie gdb verwendet werden.
quelle
try { .. } catch(...) { ... }
für das Fangen mit Signal / Sigaction implementiert haben, würde ich es nicht "Fangen" nennen :) Wenn in einem Signalhandler, ist es für den Programmierer relativ schwer zu wissen, wo im Code der Absturz passiert ist (ich spreche über das programmgesteuerte Erkennen) im Vergleich zu try / catch.Auf diese Weise können Sie den Ausnahmetyp von innen
catch(...)
mit GCC zurückentwickeln, falls dies erforderlich ist (kann nützlich sein, wenn Unbekanntes aus einer Drittanbieter-Bibliothek abgefangen wird):und wenn Sie es sich leisten können, Boost zu verwenden , können Sie Ihren Fangbereich (außen) noch einfacher und möglicherweise plattformübergreifend gestalten
quelle
Beachten Sie, dass das
...
Innerecatch
eine echte Ellipse ist, dh. drei Punkte.Da C ++ - Ausnahmen jedoch nicht unbedingt Unterklassen einer Basisklasse
Exception
sind, kann die bei Verwendung dieses Konstrukts ausgelöste Ausnahmevariable nicht angezeigt werden.quelle
catch
vom vorhandenen Code-Platzhalter in einem Kommentar (// ...
) zu unterscheiden, der offensichtlich keine C ++ - Syntax ist.Es ist (in C ++) nicht möglich, alle Ausnahmen portabel abzufangen. Dies liegt daran, dass einige Ausnahmen keine Ausnahmen in einem C ++ - Kontext sind. Dies schließt Dinge wie Division durch Null Fehler und andere ein. Es ist möglich, sich zu hacken und so Ausnahmen auszulösen, wenn diese Fehler auftreten, aber es ist nicht einfach und sicherlich nicht einfach, auf tragbare Weise richtig zu machen.
Wenn Sie alle STL-Ausnahmen abfangen möchten, können Sie dies tun
Damit können Sie verwenden
e.what()
, was a zurückgibtconst char*
, das Ihnen mehr über die Ausnahme selbst erzählen kann. Dies ist das Konstrukt, das dem Java-Konstrukt, nach dem Sie gefragt haben, am ähnlichsten ist.Dies hilft Ihnen nicht, wenn jemand dumm genug ist, eine Ausnahme auszulösen, von der nicht geerbt wird
std::exception
.quelle
Kurz gesagt, verwenden
catch(...)
. Beachten Sie jedoch, dasscatch(...)
dies in Verbindung mitthrow;
grundsätzlich verwendet werden soll:Dies ist die richtige Verwendung
catch(...)
.quelle
Foo
Destruktor ausführen würde ? Ich dachte, das wäre der springende Punkt bei RAII. Wenn Sie jedoch einen Zeiger auf a benötigen,Foo
anstatt nur denFoo
auf dem Stapel zu erstellen , müssen Sie den Zeiger in etwas anderes einschließen, das auf dem Stapel deklariert ist.Dies ist schriftlich möglich:
Hier besteht jedoch ein nicht wahrnehmbares Risiko: Sie können den genauen Fehlertyp, der in den
try
Block geworfen wurde, nicht finden. Verwenden Sie diese Art von Fehler,catch
wenn Sie sicher sind, dass das Programm unabhängig von der Art der Ausnahme bestehen bleiben muss auf die imcatch
Block definierte Weise .quelle
Sie können verwenden
aber das ist sehr gefährlich. In seinem Buch Debugging Windows erzählt John Robbins eine Kriegsgeschichte über einen wirklich bösen Fehler, der durch einen catch-Befehl (...) maskiert wurde. Sie sind viel besser dran, bestimmte Ausnahmen zu erwischen. Fangen Sie alles auf, was Sie denken, dass Ihr try-Block vernünftigerweise auslösen könnte, aber lassen Sie den Code eine Ausnahme höher auslösen, wenn etwas wirklich Unerwartetes passiert.
quelle
Lassen Sie mich dies hier nur erwähnen: das Java
darf NICHT alle Ausnahmen abfangen! Ich habe so etwas schon einmal erlebt und es ist wahnsinnig; Ausnahme ergibt sich von Throwable. Um also buchstäblich alles zu fangen, möchten Sie KEINE Ausnahmen fangen. du willst Throwable fangen.
Ich weiß, es klingt pingelig, aber wenn Sie mehrere Tage damit verbracht haben, herauszufinden, woher die "nicht erfasste Ausnahme" in Code stammt, der von einem try ... catch (Ausnahme e) "- Block umgeben war, bleibt es dabei Sie.
quelle
catch(Exception)
möglicherweise nicht alle Ausnahmen in Java abgefangen, Sie verwechseln es mit C # ... Java =catch(Thowable)
, C # =catch(Exception)
. Verwechsle sie nicht.CoderMalfunctionError
(was eigentlich eine echte Java-Error
Unterklasse ist ... obwohl es nicht bedeutet, wie es sich anhört.)Nun, wenn Sie alle Ausnahmen abfangen möchten, um beispielsweise einen Minidump zu erstellen ...
Jemand hat die Arbeit unter Windows gemacht.
Siehe http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus In diesem Artikel erklärt er, wie er herausgefunden hat, wie alle Arten von Ausnahmen abgefangen werden können, und stellt Code bereit, der funktioniert.
Hier ist die Liste, die Sie fangen können:
Und die Verwendung: CCrashHandler ch; ch.SetProcessExceptionHandlers (); // mache das für einen Thread ch.SetThreadExceptionHandlers (); // für jeden Thred
Standardmäßig wird ein Minidump im aktuellen Verzeichnis erstellt (crashdump.dmp).
quelle
Zweifelhaft. Sie wissen bereits, dass Ihr Code defekt ist, weil er abstürzt. Essensausnahmen können dies maskieren, aber das wird wahrscheinlich nur zu noch schlimmeren, subtileren Fehlern führen.
Was Sie wirklich wollen, ist ein Debugger ...
quelle
Können Sie Ihre JNI-verwendende Java-Anwendung über ein Konsolenfenster ausführen (über eine Java-Befehlszeile starten), um festzustellen, ob ein Bericht darüber vorliegt, was möglicherweise vor dem Absturz der JVM erkannt wurde? Wenn Sie direkt als Java-Fensteranwendung ausgeführt werden, fehlen möglicherweise Meldungen, die angezeigt werden, wenn Sie stattdessen über ein Konsolenfenster ausgeführt werden.
Zweitens können Sie Ihre JNI-DLL-Implementierung stubben, um zu zeigen, dass Methoden in Ihrer DLL von JNI eingegeben werden, Sie ordnungsgemäß zurückkehren usw.?
Haben Sie für den Fall, dass das Problem in einer falschen Verwendung einer der JNI-Schnittstellenmethoden aus dem C ++ - Code liegt, überprüft, ob einige einfache JNI-Beispiele kompiliert wurden und mit Ihrem Setup funktionieren? Ich denke insbesondere an die Verwendung der JNI-Schnittstellenmethoden zum Konvertieren von Parametern in native C ++ - Formate und zum Umwandeln von Funktionsergebnissen in Java-Typen. Es ist nützlich, diese zu stubben, um sicherzustellen, dass die Datenkonvertierungen funktionieren und Sie bei den COM-ähnlichen Aufrufen der JNI-Schnittstelle nicht durcheinander geraten.
Es gibt noch andere Dinge zu überprüfen, aber es ist schwierig, irgendwelche vorzuschlagen, ohne mehr darüber zu wissen, was Ihre nativen Java-Methoden sind und was die JNI-Implementierung von ihnen versucht. Es ist nicht klar, dass das Abfangen einer Ausnahme von der C ++ - Codeebene mit Ihrem Problem zusammenhängt. (Sie können die JNI-Schnittstelle verwenden, um die Ausnahme als Java-Schnittstelle erneut auszulösen. Aus Ihren Angaben geht jedoch nicht hervor, dass dies hilfreich sein wird.)
quelle
Für das eigentliche Problem, dass ein Programm, das JNI verwendet, nicht ordnungsgemäß debuggt werden kann (oder der Fehler nicht auftritt, wenn es unter einem Debugger ausgeführt wird):
In diesem Fall ist es oft hilfreich, Java-Wrapper um Ihre JNI-Aufrufe hinzuzufügen (dh alle nativen Methoden sind privat und Ihre öffentlichen Methoden in der Klasse rufen sie auf), die eine grundlegende Überprüfung der Integrität durchführen (überprüfen Sie, ob alle "Objekte" freigegeben sind und "Objekte"). werden nach dem Freigeben nicht verwendet) oder synchronisiert (synchronisieren Sie einfach alle Methoden von einer DLL zu einer einzelnen Objektinstanz). Lassen Sie die Java-Wrapper-Methoden den Fehler protokollieren und eine Ausnahme auslösen.
Dies hilft oft dabei, den eigentlichen Fehler (der überraschenderweise hauptsächlich im Java-Code enthalten ist, der nicht der Semantik der aufgerufenen Funktionen entspricht und einige unangenehme Double-Frees oder ähnliches verursacht) leichter zu finden als den Versuch, ein massiv paralleles Java-Programm in einem zu debuggen nativer Debugger ...
Wenn Sie die Ursache kennen, behalten Sie den Code in Ihren Wrapper-Methoden bei, um dies zu vermeiden. Lassen Sie Ihre Wrapper-Methoden lieber Ausnahmen auslösen, als dass Ihr JNI-Code die VM zum Absturz bringt ...
quelle
Nun, das hängt wirklich von der Compiler-Umgebung ab. gcc fängt diese nicht. Visual Studio und das letzte Borland, das ich verwendet habe, haben es getan.
Die Schlussfolgerung zu Abstürzen lautet also, dass dies von der Qualität Ihrer Entwicklungsumgebung abhängt.
Die C ++ - Spezifikation besagt, dass catch (...) Ausnahmen abfangen muss, dies jedoch nicht in allen Fällen.
Zumindest von dem, was ich versucht habe.
quelle
Sei vorsichtig
fängt nur Ausnahmen auf Sprachebene ab, andere Ausnahmen / Fehler auf niedriger Ebene mögen
Access Violation
und werdenSegmentation Fault
nicht abgefangen.quelle