sptk



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Exception stack traces



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

List hosted by Total Knowledge

Authoright © Total Knowledge: 2005