Skip to content

Commit 9e950ae

Browse files
committed
backtrace with demangling
1 parent 0962de6 commit 9e950ae

1 file changed

Lines changed: 54 additions & 10 deletions

File tree

inst/include/Rcpp/exceptions.h

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,64 @@
55
#include <Rinternals.h>
66
#include <sstream>
77

8+
// for backtraces
9+
#if defined(__GCC__) || defined(__clang__)
10+
#include <execinfo.h>
11+
#endif
12+
813
#define GET_STACKTRACE() stack_trace( __FILE__, __LINE__ )
914

1015
namespace Rcpp{
1116

1217
class exception : public std::exception {
1318
public:
14-
explicit exception(const char* message_) : message(message_){}
19+
explicit exception(const char* message_) : message(message_) {
20+
21+
#if defined(__GCC__) || defined(__clang__)
22+
23+
const size_t max_depth = 100;
24+
size_t stack_depth;
25+
void *stack_addrs[max_depth];
26+
char **stack_strings;
27+
28+
stack_depth = backtrace(stack_addrs, max_depth);
29+
stack_strings = backtrace_symbols(stack_addrs, stack_depth);
30+
std::vector<std::string> demangled;
31+
demangled.reserve(stack_depth);
32+
33+
// demangle the lines and add back in
34+
for (int i=0; i < stack_depth-2; ++i) {
35+
36+
std::string buffer( stack_strings[i] );
37+
std::string buffer2(stack_strings[i] );
38+
39+
std::string to_add;
40+
41+
size_t demangle_end = buffer.find_last_of('+') - 1;
42+
buffer.resize( buffer.find_last_of('+') - 1 ) ;
43+
size_t demangle_begin = buffer.find_last_of(' ');
44+
to_add += std::string( buffer.begin(), buffer.begin() + demangle_begin + 1 );
45+
buffer.erase(
46+
buffer.begin(),
47+
buffer.begin() + buffer.find_last_of(' ') + 1
48+
) ;
49+
to_add += Rcpp::demangle(buffer);
50+
to_add += std::string( buffer2.begin() + demangle_end, buffer2.end() );
51+
demangled.emplace_back(to_add);
52+
}
53+
54+
message += "\n\nTraceback (most recent call first):\n";
55+
56+
for (int i=0; i < stack_depth-2; ++i) {
57+
message += demangled[i];
58+
message += "\n";
59+
}
60+
61+
free(stack_strings); // malloc()ed by backtrace_symbols
62+
63+
#endif
64+
65+
}
1566
exception(const char* message_, const char* file, int line ): message(message_){
1667
rcpp_set_stack_trace( stack_trace(file,line) ) ;
1768
}
@@ -21,17 +72,10 @@ class exception : public std::exception {
2172
std::string message ;
2273
} ;
2374

24-
// simple helper
25-
static std::string toString(const int i) {
26-
std::ostringstream ostr;
27-
ostr << i;
28-
return ostr.str();
29-
}
30-
3175
class no_such_env : public std::exception{
3276
public:
3377
no_such_env( const std::string& name ) throw() : message( std::string("no such environment: '") + name + "'" ){}
34-
no_such_env( int pos ) throw() : message( "no environment in given position '" + toString(pos) + "'") {}
78+
no_such_env( int pos ) throw() : message( "no environment in given position '" + std::to_string(pos) + "'") {}
3579
virtual ~no_such_env() throw(){}
3680
virtual const char* what() const throw(){ return message.c_str() ; }
3781
private:
@@ -41,7 +85,7 @@ class no_such_env : public std::exception{
4185
class file_io_error : public std::exception {
4286
public:
4387
file_io_error(const std::string& file_) throw() : message( std::string("file io error: '") + file_ + "'" ), file(file_) {}
44-
file_io_error(int code, const std::string& file_) throw() : message( "file io error " + toString(code) + ": '" + file_ + "'"), file(file_) {}
88+
file_io_error(int code, const std::string& file_) throw() : message( "file io error " + std::to_string(code) + ": '" + file_ + "'"), file(file_) {}
4589
file_io_error(const std::string& msg, const std::string& file_) throw() : message( msg + ": '" + file_ + "'"), file(file_) {}
4690
virtual ~file_io_error() throw(){}
4791
virtual const char* what() const throw(){ return message.c_str() ; }

0 commit comments

Comments
 (0)