From 57bbb6651bfc10d9f2404164e3303c3376dfc62c Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 4 Mar 2008 19:26:24 +0000 Subject: Added backtrace support to the Exception system. It's pretty simple, if it's enabled, and the compiler/libc support it, then you just get backtraces, if not you get a message about it not being supported. It probably shouldn't be enabled in most production environments, since it does happen for every exception, and could be memory and time consuming. --- src/exceptionbase.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++---- src/exceptionbase.h | 12 +++++++++ 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/exceptionbase.cpp b/src/exceptionbase.cpp index 61bbcb4..6e5ae10 100644 --- a/src/exceptionbase.cpp +++ b/src/exceptionbase.cpp @@ -11,45 +11,70 @@ Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : nErrorCode( 0 ), sWhat( NULL ) +#ifdef LIBBU_EXCEPTION_BACKTRACE + , sBT( NULL ) +#endif { va_list ap; va_start(ap, lpFormat); setWhat( lpFormat, ap ); va_end(ap); +#ifdef LIBBU_EXCEPTION_BACKTRACE + createBacktrace(); +#endif } Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : nErrorCode( nCode ), sWhat( NULL ) +#ifdef LIBBU_EXCEPTION_BACKTRACE + , sBT( NULL ) +#endif { va_list ap; va_start(ap, lpFormat); setWhat( lpFormat, ap ); va_end(ap); +#ifdef LIBBU_EXCEPTION_BACKTRACE + createBacktrace(); +#endif } Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : nErrorCode( nCode ), sWhat( NULL ) +#ifdef LIBBU_EXCEPTION_BACKTRACE + , sBT( NULL ) +#endif { +#ifdef LIBBU_EXCEPTION_BACKTRACE + createBacktrace(); +#endif } Bu::ExceptionBase::ExceptionBase( const ExceptionBase &e ) throw () : nErrorCode( e.nErrorCode ), sWhat( NULL ) +#ifdef LIBBU_EXCEPTION_BACKTRACE + , sBT( NULL ) +#endif { setWhat( e.sWhat ); +#ifdef LIBBU_EXCEPTION_BACKTRACE + createBacktrace(); +#endif } Bu::ExceptionBase::~ExceptionBase() throw() { - if( sWhat ) - { - delete[] sWhat; - sWhat = NULL; - } + delete[] sWhat; + sWhat = NULL; +#ifdef LIBBU_EXCEPTION_BACKTRACE + delete[] sBT; + sBT = NULL; +#endif } void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) @@ -82,3 +107,43 @@ int Bu::ExceptionBase::getErrorCode() return nErrorCode; } +#ifdef LIBBU_EXCEPTION_BACKTRACE +const char *Bu::ExceptionBase::getBacktrace() const throw() +{ + return sBT; +} + +#include "bu/fstring.h" +#include + +void Bu::ExceptionBase::createBacktrace() +{ + void *array[1000]; + size_t size; + char **strings; + size_t i; + + size = backtrace (array, 1000); + strings = backtrace_symbols (array, size); + + Bu::FString s; + s.format("Obtained %zd stack frames.\n", size ); + + for (i = 0; i < size; i++) + { + s += strings[i]; + s += "\n"; + } + + free (strings); + + sBT = new char[s.getSize()+1]; + strcpy( sBT, s.getStr() ); +} + +#else +const char *Bu::ExceptionBase::getBacktrace() const throw() +{ + return "Backtrace support is not compiled in.\n"; +} +#endif diff --git a/src/exceptionbase.h b/src/exceptionbase.h index 391e41d..4d1d2ff 100644 --- a/src/exceptionbase.h +++ b/src/exceptionbase.h @@ -12,6 +12,12 @@ #include #include +// This shouldn't normally be defined here, I don't think it's all that portable +// and it also changes the class interface, we should find out how much of +// an issue that is, we could just put in an empty getBacktrace() function for +// when you don't have support for it... +#define LIBBU_EXCEPTION_BACKTRACE + namespace Bu { /** @@ -83,9 +89,15 @@ namespace Bu */ void setWhat( const char *lpText ); + const char *getBacktrace() const throw(); + private: int nErrorCode; /**< The code for the error that occured. */ char *sWhat; /**< The text string telling people what went wrong. */ +#ifdef LIBBU_EXCEPTION_BACKTRACE + char *sBT; /**< The backtrace text. */ + void createBacktrace(); +#endif }; } -- cgit v1.2.3