[Rcpp-commits] r941 - in pkg/Rcpp: R src src/Rcpp
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Tue Mar 23 17:10:26 CET 2010
Author: romain
Date: 2010-03-23 17:10:26 +0100 (Tue, 23 Mar 2010)
New Revision: 941
Added:
pkg/Rcpp/src/debugging.cpp
Modified:
pkg/Rcpp/R/exceptions.R
pkg/Rcpp/src/Evaluator.cpp
pkg/Rcpp/src/Rcpp.h
pkg/Rcpp/src/Rcpp/RObject.h
pkg/Rcpp/src/RcppCommon.h
pkg/Rcpp/src/exceptions.cpp
Log:
added experimental mechanism to grab a c++ stack trace
Modified: pkg/Rcpp/R/exceptions.R
===================================================================
--- pkg/Rcpp/R/exceptions.R 2010-03-23 15:23:59 UTC (rev 940)
+++ pkg/Rcpp/R/exceptions.R 2010-03-23 16:10:26 UTC (rev 941)
@@ -15,14 +15,15 @@
# You should have received a copy of the GNU General Public License
# along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
-cpp_exception <- function( message = "C++ exception", class = NULL ){
+cpp_exception <- function( message = "C++ exception", class = NULL, cppstack = rcpp_get_current_stack_trace() ){
callstack <- sys.calls()
ncalls <- length(callstack)
call <- if( ncalls > 1L) callstack[[ ncalls - 1L ]] else match.call()
classes <- c( class, "C++Error", "error", "condition" )
condition <- structure(
- list( message = message, call = call ),
+ list( message = message, call = call, cppstack = cppstack ),
class = classes )
+ rcpp_set_current_stack_trace( NULL )
stop( condition )
}
@@ -71,3 +72,12 @@
.rcpp_error_recorder(cond)
}
+rcpp_set_current_stack_trace <- function( trace ){
+ exceptions[["stack_trace"]] <- trace
+}
+rcpp_get_current_stack_trace <- function(){
+ exceptions[["stack_trace"]]
+}
+rcpp_set_current_stack_trace( NULL )
+
+
Modified: pkg/Rcpp/src/Evaluator.cpp
===================================================================
--- pkg/Rcpp/src/Evaluator.cpp 2010-03-23 15:23:59 UTC (rev 940)
+++ pkg/Rcpp/src/Evaluator.cpp 2010-03-23 16:10:26 UTC (rev 941)
@@ -29,9 +29,8 @@
const char* Evaluator::eval_error::what() const throw(){ return message.c_str() ; }
SEXP Evaluator::run(SEXP expr, SEXP env) throw(eval_error) {
+ SEXP call = PROTECT( Rf_lang3( Rf_install("rcpp_tryCatch") , expr, env ) ) ;
- SEXP call = PROTECT( Rf_lang3( Rf_install("rcpp_tryCatch") , expr, env ) ) ;
-
Environment RCPP = Environment::Rcpp_namespace();
/* call the tryCatch call */
Modified: pkg/Rcpp/src/Rcpp/RObject.h
===================================================================
--- pkg/Rcpp/src/Rcpp/RObject.h 2010-03-23 15:23:59 UTC (rev 940)
+++ pkg/Rcpp/src/Rcpp/RObject.h 2010-03-23 16:10:26 UTC (rev 941)
@@ -298,6 +298,15 @@
};
+class exception : public std::exception {
+ public:
+ exception(const char* message_, const char* file, int line ) ;
+ virtual ~exception() throw() ;
+ virtual const char* what() const throw() { return message.c_str() ; };
+ private:
+ std::string message ;
+} ;
+
} // namespace Rcpp
#endif
Modified: pkg/Rcpp/src/Rcpp.h
===================================================================
--- pkg/Rcpp/src/Rcpp.h 2010-03-23 15:23:59 UTC (rev 940)
+++ pkg/Rcpp/src/Rcpp.h 2010-03-23 16:10:26 UTC (rev 941)
@@ -46,12 +46,12 @@
#include <RcppVectorView.h>
/* new api */
+#include <Rcpp/exceptions.h>
#include <Rcpp/RObject.h>
#include <Rcpp/Named.h>
#include <Rcpp/S4.h>
-#include <Rcpp/exceptions.h>
#include <Rcpp/clone.h>
#include <Rcpp/grow.h>
#include <Rcpp/Dimension.h>
Modified: pkg/Rcpp/src/RcppCommon.h
===================================================================
--- pkg/Rcpp/src/RcppCommon.h 2010-03-23 15:23:59 UTC (rev 940)
+++ pkg/Rcpp/src/RcppCommon.h 2010-03-23 16:10:26 UTC (rev 941)
@@ -112,7 +112,7 @@
#include <tr1/unordered_set>
#endif
-std::string demangle( const char* name) ;
+std::string demangle( const std::string& name) ;
#define DEMANGLE(__TYPE__) demangle( typeid(__TYPE__).name() ).c_str()
// include R headers, but set R_NO_REMAP and access everything via Rf_ prefixes
@@ -205,6 +205,10 @@
#define RCPP_DEBUG( fmt , ... )
#endif
+SEXP stack_trace( const char *file, int line) ;
+#define GET_STACKTRACE() stack_trace( __FILE__, __LINE__ )
+#define Rcpp_error(MESSAGE) throw new Rcpp::exception( MESSAGE, __FILE__, __LINE__ )
+
// DO NOT CHANGE THE ORDER OF THESE INCLUDES
#include <Rcpp/traits/integral_constant.h>
#include <Rcpp/traits/same_type.h>
Added: pkg/Rcpp/src/debugging.cpp
===================================================================
--- pkg/Rcpp/src/debugging.cpp (rev 0)
+++ pkg/Rcpp/src/debugging.cpp 2010-03-23 16:10:26 UTC (rev 941)
@@ -0,0 +1,70 @@
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
+//
+// debugging.cpp: R/C++ interface class library -- debugging helpers
+//
+// Copyright (C) 2010 Dirk Eddelbuettel and Romain Francois
+//
+// This file is part of Rcpp.
+//
+// Rcpp is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// Rcpp is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
+
+#include <Rcpp.h>
+
+#ifdef __GNUC__
+#include <execinfo.h>
+#include <cxxabi.h>
+
+static std::string demangler_one( const char* input){
+ static std::string buffer ;
+ buffer = input ;
+ buffer.resize( buffer.find_last_of( '+' ) - 1 ) ;
+ buffer.erase(
+ buffer.begin(),
+ buffer.begin() + buffer.find_last_of( ' ' ) + 1) ;
+ return demangle( buffer) ;
+}
+
+/* inspired from http://tombarta.wordpress.com/2008/08/01/c-stack-traces-with-gcc/ */
+SEXP stack_trace( const char *file, int line) {
+ const size_t max_depth = 100;
+ size_t stack_depth;
+ void *stack_addrs[max_depth];
+ char **stack_strings;
+
+ stack_depth = backtrace(stack_addrs, max_depth);
+ stack_strings = backtrace_symbols(stack_addrs, stack_depth);
+
+ std::string current_line ;
+
+ Rcpp::CharacterVector res( stack_depth - 1) ;
+ std::transform(
+ stack_strings + 1, stack_strings + stack_depth,
+ res.begin(),
+ demangler_one
+ ) ;
+ free(stack_strings); // malloc()ed by backtrace_symbols
+
+ Rcpp::List trace = Rcpp::List::create(
+ Rcpp::Named( "file" ) = file,
+ Rcpp::Named( "line" ) = line,
+ Rcpp::Named( "stack" ) = res ) ;
+ trace.attr("class") = "Rcpp_stack_trace" ;
+ return trace ;
+}
+
+#else
+SEXP stack_trace( const char *file, int line) {
+ return R_NilValue ;
+}
+#endif
Modified: pkg/Rcpp/src/exceptions.cpp
===================================================================
--- pkg/Rcpp/src/exceptions.cpp 2010-03-23 15:23:59 UTC (rev 940)
+++ pkg/Rcpp/src/exceptions.cpp 2010-03-23 16:10:26 UTC (rev 941)
@@ -21,6 +21,15 @@
#include <Rcpp.h>
+namespace Rcpp{
+ exception::exception( const char* message_, const char* file, int line) : message(message_){
+ SEXP call = PROTECT( Rf_lang2( Rf_install("rcpp_set_current_stack_trace") , stack_trace(file,line) ) ) ;
+ Rf_eval( call, R_FindNamespace( Rf_mkString( "Rcpp") ) ) ;
+ UNPROTECT(1) ;
+ }
+ exception::~exception() throw(){}
+}
+
/* for now, the fancy exception handling is only available in GCC,
simply because we've not investigated if it is available in other
compilers */
@@ -29,11 +38,11 @@
#include <exception_defines.h>
#include <cxxabi.h>
-std::string demangle( const char* name){
+std::string demangle( const std::string& name ){
std::string real_class ;
int status =-1 ;
char *dem = 0;
- dem = abi::__cxa_demangle(name, 0, 0, &status);
+ dem = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
if( status == 0 ){
real_class = dem ;
free(dem);
@@ -48,8 +57,8 @@
std::string exception_class ;
bool has_exception_class = false;
- std::string exception_what ;
-
+ std::string exception_what ;
+
// Make sure there was an exception; terminate is also called for an
// attempt to rethrow when there is no suitable exception.
std::type_info *t = abi::__cxa_current_exception_type();
@@ -73,12 +82,10 @@
// If the exception is derived from std::exception, we can give more
// information.
- try {
+ try {
__throw_exception_again;
-#ifdef __EXCEPTIONS
} catch (std::exception &exc) {
exception_what = exc.what() ;
-#endif
} catch (...) {
exception_what = "unrecognized exception" ;
}
@@ -87,8 +94,8 @@
Rf_lang3(
Rf_install("cpp_exception"),
Rf_mkString(exception_what.c_str()),
- has_exception_class ? Rf_mkString(exception_class.c_str()) : R_NilValue
- ), R_FindNamespace(Rf_mkString("Rcpp"))
+ has_exception_class ? Rf_mkString(exception_class.c_str()) : R_NilValue),
+ R_FindNamespace(Rf_mkString("Rcpp"))
) ;
}
@@ -98,11 +105,12 @@
Rf_lang3(
Rf_install("cpp_exception"),
Rf_mkString("exception : we don't know how to get the exception message with your compiler, patches welcome"),
- R_NilValue ), R_FindNamespace(Rf_mkString("Rcpp"))
+ R_NilValue),
+ R_FindNamespace(Rf_mkString("Rcpp"))
) ;
}
-std::string demangle( const char* name){
- return std::string( name ) ;
+std::string demangle( const std::string& name ){
+ return name ;
}
#endif
SEXP initUncaughtExceptionHandler(){
More information about the Rcpp-commits
mailing list