in CException constructor. Alexey Parshin wrote:
Не смешно. Ты видел - сколько там кода? Один класс sym_engine - 650 строк. Заключение - к терапевту. 2005/10/2, Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>:take a look at http://www.codeproject.com/cpp/exception.asp It has instructions on how to write that functionality for VC++. I'd do it myself, if I had anywhere to debug it ;-) Alexey Parshin wrote:First, do you really need this? It's a feature that is only available under g++. It's against of the project idea - any feature is available on all platforms. So, if you want it - find the equvalent solution for Windows, an we put it in. Otherwise - I'm sorry.. 2005/10/2, Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>:Attached is a patch that allows to print stack trace from exception handlers that catch CException-derived exceptions (did I use word "exception" enough time while describing this exception handler enhancement?) In order to enable it, one has to be using g++ to compile SPTK, and one has to pass --enable-stacktrace option to configure. Otherwise all this functionality becomes noop. The interface is rather simple - stack trace info is collected automagically at the moment exception object is created, and handler can use printStackTrace(std::ostream&) function to output the exception. Now, one thing that is missing, is printing out of the trace in case exception wasn't caugt. I am pretty sure it is doable, but don't see _much_ point in bothering. If one wants that kind of thing, just enclose whole main function in try-catch block. Of course that wouldn't address exception in static object constructor, but such exceptions are bad idea anyways. Another TODO, is obviously writing similar functionality for VC++ (which is possible - I know for sure - I just don't have tools to debug that). OK to put it in? -- Ilya A. Volynets-Evenbakh Total Knowledge. CTO http://www.total-knowledge.com diff --git a/configure.in b/configure.in --- a/configure.in +++ b/configure.in @@ -63,6 +63,7 @@ AC_ARG_ENABLE(excel, [ --enable-exce AC_ARG_ENABLE(odbc, [ --enable-odbc use ODBC if installed (default=yes)]) AC_ARG_ENABLE(fltk, [ --enable-fltk use FLTK if installed (default=yes)]) AC_ARG_ENABLE(examples, [ --enable-examples build examples (default=no)]) +AC_ARG_ENABLE(stacktrace,[ --enable-stacktrace enable stack traces in exception handlers(default=yes)]) if test x$enable_debug = xyes; then DEBUGFLAG="-g3 -O0" @@ -192,6 +193,12 @@ AC_SUBST(POSTBUILD) AC_CHECK_LIB(pthread,pthread_rwlock_timedrdlock,AC_DEFINE(HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK,[1],[Have pthread_rwlock_timedrdlock])) AC_CHECK_LIB(pthread,pthread_rwlock_timedwrlock,AC_DEFINE(HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK,[1],[Have pthread_rwlock_timedwrlock])) +AC_LANG(C++) dnl switch over to C++, since cxxabi.h is C++ file +AC_CHECK_HEADERS(execinfo.h cxxabi.h,[], [enable_stacktrace=no]) +if test x"$enable_stacktrace" = xno; then + AC_DEFINE(SPTK_STACK_TRACE, [1], [Enable stack traces in exceptions]) +fi + dnl Write all of the files... AC_CONFIG_HEADERS(sptk3/sptk-config.h) AC_OUTPUT(Makefile sptk3/Makefile sptk3/excel/Makefile sptk3/xml/Makefile examples/Makefile .themes.sptk/Makefile) @@ -236,6 +243,12 @@ else echo "Debug info: generated ($DEBUGFLAG)" fi +if test x"$enable_stacktrace" = x"no"; then + echo "Stack traces: disabled" +else + echo "Stack traces: enabled" +fi + if test x$enable_examples = xyes; then echo "Examples: built" else diff --git a/sptk3/CException.h b/sptk3/CException.h --- a/sptk3/CException.h +++ b/sptk3/CException.h @@ -39,6 +39,10 @@ class SP_EXPORT CException : public std: std::string m_text; ///< The exception text std::string m_description; ///< The extended error information std::string m_fullMessage; ///< The complete error information combining everything together +#ifdef SPTK_EXCEPTION_TRACE + typedef __gnu_cxx::slist<std::string> trace_t; + trace_t trace; ///< The list of functions on call stack at time of exception creation +#endif /* SPTK_EXCEPTION_TRACE */ public: /// Constructor /// @param text std::string, the exception text @@ -64,6 +68,10 @@ public: /// Returns exception description std::string description() const { return m_description; } + + /// Pritnts functions that where on call stack + /// at the time exception was thrown + void printStackTrace(std::ostream& os); }; #define throwException(msg) throw CException(msg,__FILE__,__LINE__) diff --git a/src/CException.cpp b/src/CException.cpp --- a/src/CException.cpp +++ b/src/CException.cpp @@ -27,6 +27,11 @@ #include <sptk3/CException.h> #include <sptk3/CStrings.h> +#ifdef SPTK_EXCEPTION_TRACE +#include <execinfo.h> +#include <iostream> +#include <cxxabi.h> +#endif /* SPTK_EXCEPTION_TRACE*/ using namespace std; @@ -42,4 +47,41 @@ CException::CException(string text,strin if (!m_description.empty()) m_fullMessage += "\n" + m_description; + +#ifdef SPTK_EXCEPTION_TRACE + { + void * array[MAX_TRACE]; + int nSize = backtrace(array, MAX_TRACE); + char ** symbols = backtrace_symbols(array, nSize); + for(int i=0;i<nSize;i++){ + std::string s(symbols[i]); + std::string::size_type sz=0,p=s.find('('),p2=std::string::npos; + if(p!=std::string::npos){ + p2=s.find('+',++p); + } + char* dmName=0; + int st=-1; + if(p!=std::string::npos && p2!=std::string::npos) { + std::string s2=(s.substr(p,p2-p)); + dmName=abi::__cxa_demangle(s2.c_str(),NULL,&sz,&st); + } + if(dmName&&st==0){ + s.replace(p,p2-p,dmName,sz); + free(dmName); + } + trace.push_front(s); + } + free(symbols); + } +#endif /* SPTK_EXCEPTION_TRACE */ +} + +void CException::printStackTrace(std::ostream& os) +{ +#ifdef SPTK_EXCEPTION_TRACE + os<<getMsg()<<":\n"; + for(trace_t::iterator i=trace.begin();i!=trace.end();i++){ + os<<*i<<std::endl; + } +#endif /* SPTK_EXCEPTION_TRACE */ }-- Alexey Parshin, http://www.sptk.net-- Ilya A. Volynets-Evenbakh Total Knowledge. CTO http://www.total-knowledge.com-- Alexey Parshin, http://www.sptk.net
-- Ilya A. Volynets-Evenbakh Total Knowledge. CTO http://www.total-knowledge.com
List hosted by Total Knowledge