Rcpp Version 1.0.14
Loading...
Searching...
No Matches
exceptions_impl.h
Go to the documentation of this file.
1// exceptions_impl.h: Rcpp R/C++ interface class library -- exceptions
2//
3// Copyright (C) 2012 - 2019 Dirk Eddelbuettel and Romain Francois
4// Copyright (C) 2020 Dirk Eddelbuettel, Romain Francois, and Joshua N. Pritikin
5//
6// This file is part of Rcpp.
7//
8// Rcpp is free software: you can redistribute it and/or modify it
9// under the terms of the GNU General Public License as published by
10// the Free Software Foundation, either version 2 of the License, or
11// (at your option) any later version.
12//
13// Rcpp is distributed in the hope that it will be useful, but
14// WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
20
21#ifndef Rcpp__exceptions_impl__h
22#define Rcpp__exceptions_impl__h
23
24// disable demangler on platforms where we have no support
25#ifndef RCPP_DEMANGLER_ENABLED
26# if defined(_WIN32) || \
27 defined(__FreeBSD__) || \
28 defined(__NetBSD__) || \
29 defined(__OpenBSD__) || \
30 defined(__DragonFly__) || \
31 defined(__CYGWIN__) || \
32 defined(__sun) || \
33 defined(_AIX) || \
34 defined(__MUSL__) || \
35 defined(__HAIKU__) || \
36 defined(__ANDROID__)
37# define RCPP_DEMANGLER_ENABLED 0
38# elif defined(__GNUC__) || defined(__clang__)
39# include <execinfo.h>
40# define RCPP_DEMANGLER_ENABLED 1
41# else
42# define RCPP_DEMANGLER_ENABLED 0
43# endif
44#endif
45
46namespace Rcpp {
47
48 // Extract mangled name e.g. ./test(baz+0x14)[0x400962]
49#if RCPP_DEMANGLER_ENABLED
50 static inline std::string demangler_one(const char* input) { // #nocov start
51
52 static std::string buffer;
53
54 buffer = input;
55 size_t last_open = buffer.find_last_of('(');
56 size_t last_close = buffer.find_last_of(')');
57 if (last_open == std::string::npos ||
58 last_close == std::string::npos) {
59 return input; // #nocov
60 }
61 std::string function_name = buffer.substr(last_open + 1, last_close - last_open - 1);
62 // Strip the +0x14 (if it exists, which it does not in earlier versions of gcc)
63 size_t function_plus = function_name.find_last_of('+');
64 if (function_plus != std::string::npos) {
66 }
67 buffer.replace(last_open + 1, function_name.size(), demangle(function_name));
68
69 return buffer;
70
71 }
72#endif
73
74 // thread-safe; invoked prior to throwing the exception
76 {
77#if RCPP_DEMANGLER_ENABLED
78 /* inspired from http://tombarta.wordpress.com/2008/08/01/c-stack-traces-with-gcc/ */
79 const size_t max_depth = 100;
80 int stack_depth;
82
85
86 std::transform(stack_strings + 1, stack_strings + stack_depth,
87 std::back_inserter(stack), demangler_one);
88 free(stack_strings); // malloc()ed by backtrace_symbols
89#endif
90 }
91
92 // not thread-safe; invoked after catching the exception
94 {
95 if (!stack.size()) {
97 return;
98 }
99
100 CharacterVector res(stack.size());
101 std::copy(stack.begin(), stack.end(), res.begin());
102 List trace = List::create(_["file" ] = "",
103 _["line" ] = -1,
104 _["stack"] = res);
105 trace.attr("class") = "Rcpp_stack_trace";
106 rcpp_set_stack_trace(trace); // #nocov end
107 }
108
109}
110
111#endif
iterator begin()
Definition Vector.h:333
static Vector create()
Definition Vector.h:1121
std::vector< std::string > stack
Definition exceptions.h:59
void copy_stack_trace_to_r() const
std::string demangle(const std::string &name)
Definition routines.h:192
Rcpp API.
Definition algo.h:28
static internal::NamedPlaceHolder _
Definition Named.h:64
T as(SEXP x)
Definition as.h:151
attribute_hidden SEXP rcpp_set_stack_trace(SEXP e)
Definition routines.h:186