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

romain at r-enthusiasts.com romain at r-enthusiasts.com
Thu Jun 13 10:43:15 CEST 2013


Hello,

This is somewhat of a known issue we have with windows for some time.
Thanks for looking into it.

If I apply your suggestion to the generator file and it does not break 
existing code (i.e. as defined by our unit tests), would you be willing 
to test it on your settings ?

Romain

Le 2013-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.
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> 
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel


More information about the Rcpp-devel mailing list