[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