Wie Sie wissen, die genaue Codezeile, in der eine Ausnahme verursacht worden ist?
Wenn ich eine Ausnahme generieren, auf meinen eigenen, ich kann jede info in Ausnahme: eine Reihe von code-Zeile und der name der Quell-Datei. So etwas wie dieses:
throw std::exception("myFile.cpp:255");
Aber was ist mit Ausnahmen oder Ausnahmen, die nicht generiert wurden, werden durch mich?
- Kleine Anmerkung: Das ist nicht standard-konformen code; std::exception nicht über ein Tor, dass einen string. Allerdings MSVC nicht (falsch) es zulassen...
- In der Tat. Sie sollten wirft
runtime_error
; "Ausnahme" sagt gar nichts. - stackoverflow.com/questions/3026649/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es scheint, jeder wird versuchen zu verbessern Sie Ihren code zu werfen, exceptions in Ihrem code, und niemand versucht die eigentliche Frage, die Sie gefragt.
Ist, weil es nicht getan werden kann. Wenn der code, der das auslösen der Ausnahme, die nur in binärer form (z.B. in einem LIB oder DLL-Datei), dann die Nummer der Zeile ist verschwunden, und es gibt keine Möglichkeit, schließen Sie das Objekt auf eine Zeile im Quelltext.
Eine bessere Lösung ist die Verwendung einer benutzerdefinierten Klasse und ein makro. 🙂
: std::runtime_error(std::string(file)+":"+std::to_string(line)+":"+arg)
zu vermeiden ostream manipulation.Gibt es mehrere Möglichkeiten, um herauszufinden, wo die exception geworfen wurde:
Mithilfe von compiler-Makros
Mit
__FILE__
und__LINE__
Makros zu werfen, Lage (wie schon von anderen Kommentatoren), entweder indem man Sie im std Ausnahmen als text, oder als separate Argumente für eine benutzerdefinierte Ausnahme:Entweder
oder werfen
Beachten Sie, dass auch beim kompilieren für Unicode (in Visual Studio), DATEI erweitert, um eine single-byte-string.
Das funktioniert in der debug und release. Leider, source-file-Namen mit der code-auslösen von Ausnahmen sind in der Ausgabe die ausführbare.
Stapel Wandern
Finden Sie heraus, Ausnahme-Speicherort zu Fuß auf dem Aufruf-stack.
Unter Linux mit gcc die Funktionen backtrace() und backtrace_symbols() kann man infos über den aktuellen call-stack. Finden Sie die gcc-Dokumentation wie Sie zu benutzen sind. Der code muss kompiliert werden, mit -g, so, dass die debug-Symbole in der ausführbaren Datei.
Auf Windows, Sie können zu Fuß den Stapel mit den dbghelp-Bibliothek und Ihre Funktion StackWalk64. Siehe Jochen Kalmbach ' s Artikel auf CodeProject für details. Dies funktioniert in der debug-und release -, und Sie brauchen, um zu versenden .pdb-Dateien für alle Module, die Sie möchten infos über.
Können Sie sogar kombinieren die zwei Lösungen, die durch das sammeln von call-stack info wenn Sie eine benutzerdefinierte exception geworfen wird. Der call-stack gespeichert werden können in der Ausnahme, genau wie in .NET oder Java. Beachten Sie, dass das sammeln von call-stack auf Win32 ist sehr langsam (meine Letzte test zeigte, dass ungefähr 6 gesammelten Stapel pro Sekunde). Wenn Ihr code viele Ausnahmen auslöst, ist dieser Ansatz verlangsamt das Programm erheblich.
Wenn Sie einen debug-build, und führen Sie es in der Visual Studio-debugger, dann können Sie in den debugger unterbrechen, wenn jede Art von exception geworfen wird, bevor er vermehrt in die Welt.
Aktivieren Sie diese mit der Debug > Ausnahmen Menü alternative und prüfen Sie dann,-Kennzeichnung der Arten von Ausnahmen, die Sie interessiert sind in.
Können Sie auch hinzufügen, die Fähigkeit, erstellen Sie eine dump-Datei, wenn der Quellcode der Anwendung ist Ihre eigene. Mit der dump-Datei und PDB-Dateien (Symbole) für die bestimmten bauen, Sie erhalten stacktraces mit WinDbg, zum Beispiel.
Die einfachste Lösung ist, ein makro verwenden:
Ich denke, dass ein stack-trace sollte erhalten Sie auf den Punkt.
Fand ich 2 Lösungen, die aber weder ist voll zufriedenstellend:
Wenn Sie anrufen
std::set_terminate
Sie können von dort aus drucken Sie die Aufrufliste rechts von der Dritten Ausnahme zu werfen. Leider gibt es keine Möglichkeit einer Wiederherstellung, wenn ein terminate-handler, und daher Ihre Anwendung wird sterben.Wenn Sie anrufen
std::set_unexpected
, dann müssen Sie erklären, so viele wie möglich von Ihren Funktionen mitthrow(MyControlledException)
, so dass, wenn Sie werfen, wegen der von Dritten Funktionen aufgerufen, Ihreunexpected_handler
wird in der Lage sein, um Ihnen eine sehr genaue Vorstellung davon, wo Ihre Anwendung warf.Abgesehen von der Verwendung einer benutzerdefinierten Klasse mit einem makro, wie vorgeschlagen von Frank Krüger, für Ihre eigenen Ausnahmen, sind Sie möglicherweise daran interessiert, einen Blick auf die structured exception handling Mechanismus (du bist Programmierung unter windows, richtig?)
Überprüfen Sie Die strukturierte Ausnahmebehandlung auf der MSDN-Website
Inspiriert von Frank Krüger, die Antwort und die Dokumentation für std::nested_exception, erkannte ich, dass Sie kombinieren können Frank ' s Antwort, die ich benutzt habe für eine Weile, mit std::nested_exception zu erstellen, eine vollständige Fehler-stack-Ablaufverfolgung mit der Datei & line info. Zum Beispiel mit meiner Implementierung, ausgeführt
Ausgänge
Hier ist meine Umsetzung:
``