try catch und der gezielte Absturz / Segmentation Fault
-
Guten Morgen.
Ich verwende try-catch und möchte gerne im catch einen Segmentation Fault erzeugen so wie wenn ich kein try-catch verwendet hätte.
Das Exception-Handling betreibe ich nur, damit ich Log-Meldungen ausgeben kann, bevor der Absturz passiert.
Damit man aber auch später ohne Code-Veränderung im gdb die Absturzstelle "ordentlich" sieht, hätte ich gerne ein Verhalten wie wenn kein try-catch verwerndet worden wäre.try{ testtrycatch(); } catch( const std::exception& ex ) { cout << "catch1 " << ex.what() << endl; throw ex; } catch( ... ) { cout << "catch2" << endl; throw; }
Leider funktioniert das mit throw nicht so wie ich möchte oder ich verwende throw in diesem Fall falsch?
Im gdb sieht man leider die genau Absturzstelle nicht so gut wie ohne try-catch.
Das ganze läuft unter Linux, Boost darf und kann verwendet werden, falls dies wichtig istGibt es dazu überhaupt eine Lösung?
DAKNE für eure Hilfelg Johannes
-
Segfaults sind keine exceptions. Man kann sie nicht catchen.
-
Sieht so aus, als ob ein eigener terminate-Handler gebraucht wird.
in etwa
#include <cstdlib> #include <exception> std::terminate_handler next_terminate_handler; [[noreturn]] void my_terminate() noexcept { cout << "my_terminate" << endl; if ( std::terminate_handler ) next_terminate_handler(); else std::abort(); } int main() { next_terminate_handler = std::set_terminate(my_terminate); ... }
-
@Dobi
Danke für die Auskunft!
Mir geht es nur darum, dass ich so weit wie möglich die Fehlerursache per log ausgeben kann und trotzdem die Fehlerusache im GDB sehen kann.@camper
Das heißt, ich verwende kein try-catch mehr, sondern mache das alles über den terminate Handler? Spezielle Ausgaben wie ich es mit den verschiedenen exception machen konnte ist nun nicht mehr möglich, sehe ich das richtig?
-
taff schrieb:
Das heißt, ich verwende kein try-catch mehr, sondern mache das alles über den terminate Handler? Spezielle Ausgaben wie ich es mit den verschiedenen exception machen konnte ist nun nicht mehr möglich, sehe ich das richtig?
GCC bietet die Funktion __builtin_trap für sowas.
uU ist auch ein raise(SIGTRAP) passend.
Der VC++ hat __debugbreak()idR hat jeder Compiler etwas passendes um direkt den Debugger auzurufen.
-
@Shade Of Mine
Danke, das liest sich auch sehr interessant.Macht es sinn, dass ich mir ein try-catch Makro mache, welches im Debug-Modus nicht aktiv ist und in der Release-Version ganz normal arbeitet?
-
taff schrieb:
Macht es sinn, dass ich mir ein try-catch Makro mache, welches im Debug-Modus nicht aktiv ist und in der Release-Version ganz normal arbeitet?
Nein.
Es kann aber Sinn machen im catch per Makro diese Debugger Trap aufzurufen. Prinzipiell ist das nichts anderes als ein Breakpoint den du per Code setzen kannst.
Das hilft dir beim Debuggen, aber es sollte den Programmfluss nicht beeinflussen.
-
Hmm bin nun direkt einwenig verwirrt
Es ist so, dass eine andere Person als ich, bei den Kunden die Programme supported und unter Umständen eine gdb version laufen lässt und mir dann den Backtrace zu kommen lässt.
Im Prinzip brauch ich dann keinen Breakpoint, sondern einen Backtrace den mir der Befehl bt im gdb liefert (und bei try-catch bekommt man dann ja nicht unbedingt genaue Infos)
-
taff schrieb:
catch( const std::exception& ex ) { cout << "catch1 " << ex.what() << endl; throw ex; }
throw ex;
->throw;
(besserer Stil, da Stacktrace nicht rückgesetzt wird)
-
@throwex
welcher Stacktrace wird nicht zurück gesetzt?folgender code erzeugt ein problem:
std::vector<int> vec; vec.push_back(1); vec.at(3) = 5;
ohne try
#0 0x0012d422 in __kernel_vsyscall () #1 0x002b4681 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #2 0x002b7ab2 in *__GI_abort () at abort.c:92 #3 0x0020f52f in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6 #4 0x0020d465 in ?? () from /usr/lib/libstdc++.so.6 #5 0x0020d4a2 in std::terminate() () from /usr/lib/libstdc++.so.6 #6 0x0020d5e1 in __cxa_throw () from /usr/lib/libstdc++.so.6 #7 0x001a41ff in std::__throw_out_of_range(char const*) () from /usr/lib/libstdc++.so.6 #8 0x0804e7d4 in std::vector<int, std::allocator<int> >::_M_range_check () at /usr/include/c++/4.4/bits/stl_vector.h:634 #9 std::vector<int, std::allocator<int> >::at () at /usr/include/c++/4.4/bits/stl_vector.h:652 #10 testtrycatch () at tvepg.cpp:45 #11 0x0804fa75 in Service () at test.cpp:66 #12 0x08106ad2 in TEST_main (argc=2, argv=0xbffff474) at test.cpp:997 #13 0x08106e54 in main (argc=2, argv=0xbffff474) at test.cpp:1030
mit try catch-throw
#0 0x0012d422 in __kernel_vsyscall () #1 0x002b4681 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #2 0x002b7ab2 in *__GI_abort () at abort.c:92 #3 0x0020f52f in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6 #4 0x0020d465 in ?? () from /usr/lib/libstdc++.so.6 #5 0x0020d4a2 in std::terminate() () from /usr/lib/libstdc++.so.6 #6 0x0020d55b in __cxa_rethrow () from /usr/lib/libstdc++.so.6 #7 0x080516b4 in Service () at abc.cpp:69 #8 0x08106aa2 in TEST_main (argc=2, argv=0xbffff474) at test.cpp:997 #9 0x08106e24 in main (argc=2, argv=0xbffff474) at test.cpp:1030
mit try catch-throw-ex
#0 0x0012d422 in __kernel_vsyscall () #1 0x002b4681 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #2 0x002b7ab2 in *__GI_abort () at abort.c:92 #3 0x0020f52f in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6 #4 0x0020d465 in ?? () from /usr/lib/libstdc++.so.6 #5 0x0020d4a2 in std::terminate() () from /usr/lib/libstdc++.so.6 #6 0x0020d5e1 in __cxa_throw () from /usr/lib/libstdc++.so.6 #7 0x08051749 in Service () at abc.cpp:69 #8 0x08106b32 in TEST_main (argc=2, argv=0xbffff474) at test.cpp:997 #9 0x08106eb4 in main (argc=2, argv=0xbffff474) at test.cpp:1030
Der benötigte Stacktrace wird so und so zurückgesetzt und das ergebnis zw. "throw ex" und "throw" sieht sich auch sehr ähnlich