Exception class Exception with backtrace and demangle, backtracedemangle

Source: Internet
Author: User

Exception class Exception with backtrace and demangle, backtracedemangle

C ++ exception classes have no trace of stacks. To obtain stack traces, use the following functions:

#include <execinfo.h>int backtrace(void **buffer, int size);char **backtrace_symbols(void *const *buffer, int size);void backtrace_symbols_fd(void *const *buffer, int size, int fd);

Backtrace stores the call information of the current program in the buffer, while backtrace_symbols translates the buffer into a string. The latter uses malloc, so the memory needs to be manually released.

The following code is provided in the man manual:

#include <execinfo.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>voidmyfunc3(void){   int j, nptrs;#define SIZE 100   void *buffer[100];   char **strings;   nptrs = backtrace(buffer, SIZE);   printf("backtrace() returned %d addresses\n", nptrs);   /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)      would produce similar output to the following: */   strings = backtrace_symbols(buffer, nptrs);   if (strings == NULL) {       perror("backtrace_symbols");       exit(EXIT_FAILURE);   }   for (j = 0; j < nptrs; j++)       printf("%s\n", strings[j]);   free(strings);}static void   /* "static" means don't export the symbol... */myfunc2(void){   myfunc3();}voidmyfunc(int ncalls){   if (ncalls > 1)       myfunc(ncalls - 1);   else       myfunc2();}intmain(int argc, char *argv[]){   if (argc != 2) {       fprintf(stderr, "%s num-calls\n", argv[0]);       exit(EXIT_FAILURE);   }   myfunc(atoi(argv[1]));   exit(EXIT_SUCCESS);}

Compile and execute:

$  cc -rdynamic prog.c -o prog$ ./prog 3

The output is as follows:

backtrace() returned 8 addresses./prog(myfunc3+0x1f) [0x8048783]./prog() [0x8048810]./prog(myfunc+0x21) [0x8048833]./prog(myfunc+0x1a) [0x804882c]./prog(myfunc+0x1a) [0x804882c]./prog(main+0x52) [0x8048887]/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0xb76174d3]./prog() [0x80486d1]

 

Therefore, I wrote the following exception classes. Note that the above printed results have been renamed, so we use abi :__ cxa_demangle to restore the names.

Exception. h

# Ifndef EXCEPTION_H _ # define EXCEPTION_H _ # include <string> # include <exception> class Exception: public std: exception {public: explicit Exception (const char * what ); explicit Exception (const std: string & what); virtual ~ Exception () throw (); virtual const char * what () const throw (); const char * stackTrace () const throw (); private: void fillStackTrace (); // fill in stack trace std: string demangle (const char * symbol); // anti-name adaptation std: string message _; // exception information std: string stack _; // stack trace}; # endif // EXCEPTION_H _

Exception. cpp

# Include "Exception. h "# include <cxxabi. h> # include <execinfo. h> # include <stdlib. h> # include <stdio. h> using namespace std; Exception: Exception (const char * msg): message _ (msg) {fillStackTrace ();} Exception: Exception (const string & msg ): message _ (msg) {fillStackTrace ();} Exception ::~ Exception () throw () {} const char * Exception: what () const throw () {return message _. c_str ();} const char * Exception: stackTrace () const throw () {return stack _. c_str ();} // fill stack trace void Exception: fillStackTrace () {const int len = 200; void * buffer [len]; int nptrs =: backtrace (buffer, len); // list the call relationships of the current function // convert the information obtained from the backtrace function into a string array char ** strings =: backtrace_symbols (buffer, nptrs ); if (strings) {(Int I = 0; I <nptrs; ++ I) {// TODO demangle funcion name with abi :: __cxa_demangle // strings [I] indicates the Call trace of a layer. stack _. append (demangle (strings [I]); stack _. push_back ('\ n');} free (strings) ;}// string Exception: demangle (const char * symbol) {size_t size; int status; char temp [128]; char * demangled; // first, try to demangle a c ++ name if (1 = sscanf (symbol, "% * [^ (] % * [^ _] % 127 [^) +]", temp) {if (N ULL! = (Demangled = abi ::__ cxa_demangle (temp, NULL, & size, & status) {string result (demangled); free (demangled); return result ;}} // if that didn't work, try to get a regular c symbol if (1 = sscanf (symbol, "% 127 s", temp) {return temp ;} // if all else fails, just return the symbol return symbol ;}

The test code is as follows:

#include "Exception.h"#include <stdio.h>using namespace std;class Bar{ public:  void test()  {    throw Exception("oops");  }};void foo(){  Bar b;  b.test();}int main(){  try  {    foo();  }  catch (const Exception& ex)  {    printf("reason: %s\n", ex.what());    printf("stack trace: %s\n", ex.stackTrace());  }}

The output is as follows:

reason: oopsstack trace: Exception::fillStackTrace()Exception::Exception(char const*)Bar::test()foo()./a.out(main+0xf)/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)./a.out()

Note that the-rdynamic option is added during compilation.

 

With this class, we can handle exceptions like this in the program:

try    {        //    }    catch (const Exception& ex)    {        fprintf(stderr, "reason: %s\n", ex.what());        fprintf(stderr, "stack trace: %s\n", ex.stackTrace());        abort();    }    catch (const std::exception& ex)    {        fprintf(stderr, "reason: %s\n", ex.what());        abort();    }    catch (...)    {        fprintf(stderr, "unknown exception caught \n");    throw; // rethrow    }

JavalangNullPointerException exception. No stackTrace information is output.

There is definitely a variable in your program that has no value in use, leading to a null pointer. You can debug it with the debug tool to see which variable has an exception.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.