Εξαιρέσεις στους χειριστές σήματος
Όταν ένα πρόγραμμα ματαιώνεται λόγω μιας ανεπίλυτης εξαίρεσης C++, είναι μερικές φορές δυνατή η χρήση ενός αποσφαλματωτή για την εύρεση της θέσης όπου συνέβη η εξαίρεση. Αυτό είναι πιο δύσκολο από ό,τι συνήθως, αν η εξαίρεση συνέβη από έναν χειριστή σήματος.
Αυτή η ενότητα περιγράφει κυρίως τι μπορείτε να περιμένετε σε ένα σύστημα Linux, όταν χρησιμοποιείτε το αποσφαλματωτής gdb.
First, let's look at a simple example where an exception is thrown from a normal function (no signal handler).
// without_signal.cc #include <gtkmm.h> bool throwSomething() { throw "Something"; return true; } int main(int argc, char** argv) { throwSomething(); Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.without_signal"); return app->run(); }
Here is an excerpt from a gdb session. Only the most interesting parts of the output are shown.
> gdb without_signal (gdb) run terminate called after throwing an instance of 'char const*' Program received signal SIGABRT, Aborted. (gdb) backtrace #7 0x08048864 in throwSomething () at without_signal.cc:6 #8 0x0804887d in main (argc=1, argv=0xbfffecd4) at without_signal.cc:12
Now let's see what happens when an exception is thrown from a signal handler. Here's the source code.
// with_signal.cc #include <gtkmm.h> bool throwSomething() { throw "Something"; return true; } int main(int argc, char** argv) { Glib::signal_timeout().connect(sigc::ptr_fun(throwSomething), 500); Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.with_signal"); app->hold(); return app->run(); }
And here's an excerpt from a gdb session.
> gdb with_signal (gdb) run (with_signal:2703): glibmm-ERROR **: unhandled exception (type unknown) in signal handler Program received signal SIGTRAP, Trace/breakpoint trap. (gdb) backtrace #2 0x0063c6ab in glibmm_unexpected_exception () at exceptionhandler.cc:77 #3 Glib::exception_handlers_invoke () at exceptionhandler.cc:150 #4 0x0063d370 in glibmm_source_callback (data=0x804d620) at main.cc:212 #13 0x002e1b31 in Gtk::Application::run (this=0x804f300) at application.cc:178 #14 0x08048ccc in main (argc=1, argv=0xbfffecd4) at with_signal.cc:16
To see where the exception is thrown, you can use the gdb command catch throw.
> gdb with_signal (gdb) catch throw Catchpoint 1 (throw) (gdb) run Catchpoint 1 (exception thrown), 0x00714ff0 in __cxa_throw () (gdb) backtrace #0 0x00714ff0 in __cxa_throw () from /usr/lib/i386-linux-gnu/libstdc++.so.6 #1 0x08048bd4 in throwSomething () at with_signal.cc:6 (gdb) continue Continuing. (with_signal:2375): glibmm-ERROR ** unhandled exception (type unknown) in signal handler Program received signal SIGTRAP, Trace/breakpoint trap.
If there are many caught exceptions before the interesting uncaught one, this method can be tedious. It can be automated with the following gdb commands.
(gdb) catch throw (gdb) commands (gdb) backtrace (gdb) continue (gdb) end (gdb) set pagination off (gdb) run