[Rcpp-devel] Raise a condition
Romain Francois
romain at r-enthusiasts.com
Thu Jun 19 06:51:45 CEST 2014
Le 19 juin 2014 à 01:02, Tim Keitt <tkeitt at utexas.edu> a écrit :
>
>
>
> On Wed, Jun 18, 2014 at 5:37 PM, Romain Francois <romain at r-enthusiasts.com> wrote:
> Le 19 juin 2014 à 00:30, Tim Keitt <tkeitt at utexas.edu> a écrit :
>
>> On Wed, Jun 18, 2014 at 5:22 PM, Romain Francois <romain at r-enthusiasts.com> wrote:
>> Le 19 juin 2014 à 00:15, Tim Keitt <tkeitt at utexas.edu> a écrit :
>>
>>
>>>
>>> On Wed, Jun 18, 2014 at 5:07 PM, Romain Francois <romain at r-enthusiasts.com> wrote:
>>> Le 18 juin 2014 à 23:54, Tim Keitt <tkeitt at utexas.edu> a écrit :
>>>
>>>
>>>> I'd like to raise a condition other than error or warning. Is that possible using the Rcpp api? I assume this can be done via R internals, but I'd prefer not to call error() directly (or is that the recommendation?).
>>>>
>>>> THK
>>>
>>> Definitely not. Rf_error should really only be called from C code. If you call it from C++, there is a great chance you'll lose determinism as destructors for your c++ objects are very likely not to be called. Most of the time, it will just mean you'll never release some objects to the garbage collector, but it could also get you leaks or other nice stuff depending on what your destructors were supposed to do and did not get a chance to do.
>>>
>>> That was my understanding. Just wanted to be sure it was still the case.
>>>
>>>
>>> I'm not sure Rcpp has a way to raise an R condition apart from calling stop, which usually is good enough. Otherwise, you can borrow from Rcpp11 and adapt some code from https://github.com/Rcpp11/Rcpp11/blob/450aade7338c16c34618ad0916003e8ca4fb58a6/inst/include/Rcpp/Condition.h
>>>
>>> Ah. I see. Eval "stop" in the global env with the condition as the argument. Clever.
>>
>> It is more of a hack due to lack of proper api from R.
>>
>> If you do this, make sure you don't have any c++ object in scope. Essentially that means you would evaluate `stop( condition )` in a top level catch block.
>>
>> Rcpp objects are I assume ok however.
>
> Depends what you mean by "ok". If you mean objects like NumericVector, ... their destructor is responsible for calling R_ReleaseObject, i.e. let go of the protection that was set by their constructor. If the destructor is not called because R error handling does a long jump, you will get objects forever protected.
>
> So things will seemingly work, until you exhaust the memory.
>
>> I will try "signalCondition" and see what happens.
>>
>> THK
>
>
> I can't get signalCondition to do anything.
What exactly did you try ? Did you catch the condition at the R level, with withCallingHandlers or something. Just because you don't see something does not mean nothing happens.
> This works although I've not tested it for leaks.
Easy enough to test for forgotten destructors.
#include <Rcpp.h>
using namespace Rcpp;
void raise_condition(const std::string& msg,
const std::string& type)
{
List cond;
cond["message"] = msg;
cond["call"] = R_NilValue;
cond.attr("class") = CharacterVector::create(type, "condition");
Function stopper("stop");
stopper(cond);
}
class A {
public:
A(){ Rprintf( "A::A()\n" ) ; }
~A(){ Rprintf( "A::~A()\n" ) ; }
} ;
// [[Rcpp::export]]
void test(){
A a ;
raise_condition( "foo", "bar") ;
}
/*** R
test()
*/
which gives me:
> test()
A::A()
Error: foo
So the destructor for A is never called. Not a big deal here, it was not doing anything. But might be more problematic elsewhere.
> void raise_condition(const std::string& msg,
> const std::string& type)
> {
> List cond;
> cond["message"] = msg;
> cond["call"] = R_NilValue;
> cond.attr("class") = CharacterVector::create(type, "condition");
> Function stopper("stop");
> stopper(cond);
> }
>
> THK
>
> --
> http://www.keittlab.org/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20140619/5c3cb68d/attachment-0001.html>
More information about the Rcpp-devel
mailing list