2004-08-28 16:21:25 +00:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
$Date$
|
|
|
|
$Author$
|
|
|
|
|
|
|
|
@copy © Marc Wäckerlin
|
|
|
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
|
|
|
|
|
|
|
*/
|
2004-04-21 06:39:20 +00:00
|
|
|
#include <mrw/stacktrace.hpp>
|
|
|
|
#include <mrw/exception.hpp>
|
|
|
|
#include <exception>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
namespace mrw {
|
|
|
|
|
2005-01-28 12:13:10 +00:00
|
|
|
/** @addtogroup grpStackTrace */
|
2004-04-23 16:03:29 +00:00
|
|
|
//@{
|
|
|
|
|
2005-01-28 07:42:23 +00:00
|
|
|
/** @defgroup AutoTrace Automated Unexpected and Terminate Handler
|
|
|
|
with Stack Trace
|
2004-04-23 16:03:29 +00:00
|
|
|
|
2005-01-28 07:42:23 +00:00
|
|
|
@brief Don't care about the unexpected handler, don't care about
|
|
|
|
a try-catch in the main, let the library do all the repetitive
|
|
|
|
work for you.
|
2004-04-23 16:03:29 +00:00
|
|
|
|
2005-01-28 07:42:23 +00:00
|
|
|
For all your programs it is recommended to implement an
|
|
|
|
identical unexpected handler, that rethrows, catches the @c
|
2004-04-23 16:03:29 +00:00
|
|
|
mrw::exception, @c std::exception and all unknown exceptions,
|
|
|
|
traces them and finally quits with a throw of a @c
|
2005-01-28 07:42:23 +00:00
|
|
|
std::bad_exception. You are also required to write a @c try @c
|
|
|
|
catch block around all in your @c main, so that you don't miss
|
|
|
|
any exception. The only thing that may be different from project
|
|
|
|
to project is, how tracing is done. The MRW C++ Class Library
|
|
|
|
provides you with additional libraries you can link to. By
|
|
|
|
linking to the library, you get an unexpected handler and an
|
|
|
|
exception trace in the @c main for free: You don't need to add a
|
|
|
|
single line of code, just link to one more library! The
|
|
|
|
libraries differ in how tracing is done.
|
2004-04-23 16:03:29 +00:00
|
|
|
|
|
|
|
The Implementation is done with a static instance of a class that
|
|
|
|
sets the unexpected handler in the constructor.
|
|
|
|
|
|
|
|
@section trcstderr Trace using std::cerr
|
|
|
|
|
|
|
|
If you link to the library @c libmrwexcstderr using a linker
|
2005-01-28 07:42:23 +00:00
|
|
|
option such as: @c -lmrwexcstderr, then an unexpected and a
|
|
|
|
terminate handler are registered, that trace to the standard
|
|
|
|
error stream @c std::cerr. You don't need to change a single
|
|
|
|
line in your code!
|
2004-04-23 16:03:29 +00:00
|
|
|
*/
|
|
|
|
//@{
|
|
|
|
|
|
|
|
/** @brief unexpected handler, that traces to @c std::cerr
|
|
|
|
|
|
|
|
The unexpected handler is installed automatically when you link
|
|
|
|
to @c -lmrwexcstderr. The implementation of this unexpected
|
|
|
|
handler is as follows:
|
|
|
|
|
|
|
|
@code
|
|
|
|
void unexpected_stderr() {
|
|
|
|
std::cerr<<"UNEXPECTED EXCEPTION: ----------------------------"<<std::endl;
|
|
|
|
try {
|
2005-01-28 07:42:23 +00:00
|
|
|
StackTrace::createSymtable();
|
2004-04-23 16:03:29 +00:00
|
|
|
throw;
|
|
|
|
} catch (const mrw::exception& x) {
|
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
|
|
|
<<"---------- Stack:"<<std::endl
|
2004-10-13 10:41:28 +00:00
|
|
|
<<x.stacktrace();
|
2004-04-23 16:03:29 +00:00
|
|
|
} catch (const std::exception& x) {
|
2005-01-28 07:42:23 +00:00
|
|
|
std::string st((std::string)StackTrace());
|
2004-04-23 16:03:29 +00:00
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
2005-01-28 07:42:23 +00:00
|
|
|
<<"---------- Stack: "<<std::endl<<st;
|
2004-04-23 16:03:29 +00:00
|
|
|
} catch (...) {
|
2005-01-28 07:42:23 +00:00
|
|
|
std::string st((std::string)StackTrace());
|
2004-04-23 16:03:29 +00:00
|
|
|
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
|
2005-01-28 07:42:23 +00:00
|
|
|
<<"---------- Stack:"<<std::endl<<st;
|
2004-04-23 16:03:29 +00:00
|
|
|
}
|
|
|
|
std::cerr<<"-------------------------------------------------"<<std::endl;
|
|
|
|
throw std::bad_exception();
|
|
|
|
}
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
*/
|
|
|
|
void unexpected_stderr() {
|
2004-04-21 06:39:20 +00:00
|
|
|
std::cerr<<"UNEXPECTED EXCEPTION: ----------------------------"<<std::endl;
|
2005-01-28 07:42:23 +00:00
|
|
|
try {
|
|
|
|
StackTrace::createSymtable();
|
|
|
|
throw;
|
|
|
|
} catch (const mrw::exception& x) {
|
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
|
|
|
<<"---------- Stack:"<<std::endl
|
|
|
|
<<x.stacktrace();
|
|
|
|
} catch (const std::exception& x) {
|
|
|
|
std::string st((std::string)StackTrace());
|
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
|
|
|
<<"---------- Stack:"<<std::endl<<st;
|
|
|
|
} catch (...) {
|
|
|
|
std::string st((std::string)StackTrace());
|
|
|
|
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
|
|
|
|
<<"---------- Stack:"<<std::endl<<st;
|
|
|
|
}
|
|
|
|
std::cerr<<"-------------------------------------------------"<<std::endl;
|
|
|
|
throw std::bad_exception();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @brief terminate handler, that traces to @c std::cerr
|
|
|
|
|
|
|
|
The terminate handler is installed automatically when you link
|
|
|
|
to @c -lmrwexcstderr. The implementation of this terminate
|
|
|
|
handler is as follows:
|
|
|
|
|
|
|
|
@code
|
|
|
|
void terminate_stderr() {
|
|
|
|
std::cerr<<"UNCAUGHT EXCEPTION: ----------------------------"<<std::endl;
|
2004-04-21 06:39:20 +00:00
|
|
|
try {
|
|
|
|
throw;
|
|
|
|
} catch (const mrw::exception& x) {
|
|
|
|
StackTrace::createSymtable();
|
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
|
|
|
<<"---------- Stack:"<<std::endl
|
2004-10-13 10:41:28 +00:00
|
|
|
<<x.stacktrace();
|
2004-04-21 06:39:20 +00:00
|
|
|
} catch (const std::exception& x) {
|
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
|
|
|
<<"---------- Stack: **** not available ****"<<std::endl;
|
|
|
|
} catch (...) {
|
|
|
|
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
|
|
|
|
<<"---------- Stack: **** not available ****"<<std::endl;
|
|
|
|
}
|
|
|
|
std::cerr<<"-------------------------------------------------"<<std::endl;
|
2005-01-28 07:42:23 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
*/
|
|
|
|
void terminate_stderr() {
|
|
|
|
std::cerr<<"UNCAUGHT EXCEPTION: ----------------------------"<<std::endl;
|
|
|
|
try {
|
|
|
|
throw;
|
|
|
|
} catch (const mrw::exception& x) {
|
|
|
|
StackTrace::createSymtable();
|
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
|
|
|
<<"---------- Stack:"<<std::endl
|
|
|
|
<<x.stacktrace();
|
|
|
|
} catch (const std::exception& x) {
|
|
|
|
std::cerr<<"---------- Reason:"<<std::endl
|
|
|
|
<<x.what()<<std::endl
|
|
|
|
<<"---------- Stack: **** not available ****"<<std::endl;
|
|
|
|
} catch (...) {
|
|
|
|
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
|
|
|
|
<<"---------- Stack: **** not available ****"<<std::endl;
|
|
|
|
}
|
|
|
|
std::cerr<<"-------------------------------------------------"<<std::endl;
|
|
|
|
exit(1);
|
2004-04-21 06:39:20 +00:00
|
|
|
}
|
|
|
|
|
2004-04-23 16:03:29 +00:00
|
|
|
//@}
|
|
|
|
//@}
|
|
|
|
|
2004-04-21 06:39:20 +00:00
|
|
|
class AutoStackTrace {
|
|
|
|
public:
|
|
|
|
AutoStackTrace() {
|
2004-04-23 16:03:29 +00:00
|
|
|
std::set_unexpected(&mrw::unexpected_stderr);
|
2005-01-28 07:42:23 +00:00
|
|
|
std::set_terminate(&mrw::terminate_stderr);
|
2004-04-21 06:39:20 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// initialize stack traces (load symbols)
|
|
|
|
static AutoStackTrace _autoStackTrace;
|
|
|
|
|
|
|
|
}
|