[Rcpp-devel] Problem with exceptions from standalone functions (Windows only)

Romain Francois romain at r-enthusiasts.com
Tue Jun 18 19:10:45 CEST 2013


Hi,

I have commited adding BEGIN_RCPP and END_RCPP.

Could you have a go at testing it on Windows.

Romain

Le 13/06/13 10:17, QRD a écrit :
> Hi,
>
> I've just had some trouble, on Windows with Rtools-3.0, throwing
> exceptions from within a standalone function belonging to a module:
>
> - - - - 8< - - - - crash.cpp
>
> #include <stdexcept>
> #include <Rcpp.h>
>
> int calculate(int x)
> {
>      throw std::invalid_argument("x is invalid");
> }
>
> RCPP_MODULE(Crash)
> {
>      Rcpp::function("calculate", &calculate);
> }
>
> - - - - 8< - - - - crash.R
>
> require(methods)
> require(Rcpp)
>
> dll.info <- dyn.load("crash")
> mod <- Module("Crash", dll.info, mustStart = TRUE)
>
> mod$calculate(42)
>
> - - - - 8< - - - - shell prompt
>
> R CMD SHLIB crash.cpp && Rscript crash.R
>
> This application has requested the Runtime to terminate it in an unusual way.
> Please contact the application's support team for more information.
> terminate called after throwing an instance of 'std::invalid_argument'
>    what():  x is invalid
>
> - - - - 8< - - - -
>
> This is strange as there is a BEGIN_RCPP / END_RCPP pair in the relevant
> function in Module.cpp:
>
>      extern "C" SEXP InternalFunction_invoke( SEXP args ){
>      BEGIN_RCPP
>              SEXP p = CDR(args) ;
>              XP_Function fun( CAR(p) ) ; p = CDR(p) ;
>              UNPACK_EXTERNAL_ARGS(cargs,p)
>              return fun->operator()( cargs ) ;
>      END_RCPP
>      }
>
> What seems to be going on is:
>
> Under MinGW, you can only throw/catch exceptions across a DLL boundary
> when linking to the 'DLL runtime'.  I'm basing this on quite an old
> post (from Jan 2011):
>
>      http://mingw-users.1079350.n2.nabble.com/dlls-and-exceptions-using-a-cross-compiler-td5967925.html
>
> This is my situation, because I throw the exception from crash.dll, but
> it's the above code from Module.cpp in Rcpp.dll which tries to catch it.
>
> The R scripts use a link invocation which includes '-static-libgcc':
>
>      R CMD SHLIB # ...
>      g++ -m64 -shared -s -static-libgcc -o crash.dll  # [... etc. ...]
>
> and also Rtools's 'g++ -v' reports that it was configured with
> '--disabled-shared':
>
>      Target: i686-w64-mingw32
>      Configured with: [...] --disable-shared --enable-static [...]
>      Thread model: win32
>      gcc version 4.6.3 20111208 (prerelease) (GCC)
>
> This problem doesn't show up with throwing exceptions from class member
> functions, because in that case, all the work gets done in a template, so
> the try/catch is compiled into my module's DLL.
>
> For an only-mildly-ugly workaround, I put a BEGIN_RCPP / END_RCPP pair
> around the call in the CppFunction1<OUT, U0> template class (c. line 104
> in Module_generated_CppFunction.h):
>
>      SEXP operator()(SEXP* args) {
>
>          BEGIN_RCPP    // <<-- ADD THIS
>
>          return Rcpp::module_wrap<OUT>( ptr_fun( /* ... */ ) );
>
>          END_RCPP      // <<-- AND THIS
>
>      }
>
> This is a template, so it gets compiled into my DLL, the exception never
> leaves my DLL, and all is well.
>
> Because of the '_generated_' in the filename, I haven't created a patch.
>
> If the above is right, do you think adding BEGIN_RCPP / END_RCPP pairs
> in all of the CppFunction-derived classes would be acceptable to work
> round this feature of the current build set-up under MinGW?
>
> Thanks,
>
> Ben.


-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30

R Graph Gallery: http://gallery.r-enthusiasts.com

blog:            http://blog.r-enthusiasts.com
|- http://bit.ly/Zs97qg  : highlight 0.4.1
`- http://bit.ly/10X94UM : Mobile version of the graph gallery



More information about the Rcpp-devel mailing list