One shortcoming of Erik's solution is that it can only catch the exceptions of type 
error_exception. For example it won't work if my code calls some third party library 
that can throw exceptions of some other types.

In case it's of interest to someone here is the boilerplate that I ended up using 
(note the similarity between my errMsg and error_message from Erik's solution):

extern "C" SEXP foo(SEXP x) {
        int hasFailed=0;
        char errMsg[2048];

        // NO C++ objects above this line
        try {
                // do the work
                ...
        }
        cach (std::exception e) {
                hasFailed = 1;
                strncopy(errMsg, e.what(), sizeof(errMsg));
        }
        catch (OtherException e) {
                hasFailed = 1;
                ...
        }

        // NO C++ objects below this line

        if (hasFailed) {
                error(errMsg);
        }

        return x;
}

One thing I don't like about my solution is that I need to remember to set hasFailed 
in each and every catch block (and "I often remember to forget these sort of things" 
:-)

> -----Original Message-----
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED] 
> Sent: Tuesday, March 09, 2004 4:59 AM
> To: [EMAIL PROTECTED]
> Subject: RE: [R] error() and C++ destructors
> 
> 
> And maybe I stressed Erik a bit, because he corrected himself 
> some minutes later (when I was no longer looking over his 
> shoulder). Again on behalf of Erik.
> 
> - Lennart
> 
> 
> -----Original Message-----
> From: Källen, Erik 
> Sent: 9 mars 2004 13:40
> To: Borgman, Lennart
> Subject: RE: [R] error() and C++ destructors
> 
> 
> Whoops.
> 
> This code leaks memory for the exception.
> It would be better to throw a pointer:
> 
> void my_error(const string &str) {
>       throw new error_exception(str);
> }
> 
> int my_method(int a, char *b) {
>       try {
>               return real_my_method(a, b);
>       }
>       catch (error_exception *pe) {
>               static char error_msg[SOME_LARGE_NUMBER];
>               strncpy(error_msg, pe->msg.c_str(), sizeof(error_msg));
>               delete pe;
>               error(error_msg);
>       }
> }
> 
> -----Original Message-----
> From: Borgman, Lennart 
> Sent: 9 mars 2004 13:35
> To: '[EMAIL PROTECTED]'
> Subject: RE: [R] error() and C++ destructors
> 
> 
> I am sending this reply on behalf of Erik (who is not a 
> member of this list).
> 
> - Lennart
> 
> 
> -----Original Message-----
> From: Källen, Erik 
> Sent: 9 mars 2004 11:37
> To: Borgman, Lennart
> Subject: RE: [R] error() and C++ destructors
> 
> 
> I would do something like:
> 
> class error_exception {
> public:
>       error_exception(const string &str) : msg(str) {}
>       string msg;
> };
> 
> void my_error(const string &str) {
>       throw error_exception(str);
> }
> 
> int real_my_method(int a, char *b) {
>       /*
>       some code...
>       */
>       return 0;
> }
> 
> // this is the public method:
> int my_method(int a, char *b) {
>       try {
>               return real_my_method(a, b);
>       }
>       catch (error_exception &e) {
>               error(e.msg);
>       }
> }
> 
> You could probably even create a macro like:
> #define R_METHOD_IMPL(rettype, name, paramlist) \
> rettype real_##name paramlist; \
> rettype name paramlist { \
>       try { \
>               return real_##name paramlist; \
>       } \
>       catch (error_exception &e) { \
>               error(e.msg); \
>       } \
> } \
> rettype real_##name paramlist
> 
> 
> You would use this macro like:
> R_METHOD_IMPL(int, my_method, (int a, char *b)) {
>       // source code here
> }
> 
> I think it would work, but I'm not sure (untested).
> 
> 
> /Erik Källén
> 
> 
> -----Original Message-----
> From: Vadim Ogranovich [mailto:[EMAIL PROTECTED]
> Sent: 2 mars 2004 22:00
> To: R Help List
> Subject: [R] error() and C++ destructors
> 
> 
> Hi,
>  
> I am writing C++ functions that are to be called via .Call() 
> interface. I'd been using error() (from R.h) to return to R 
> if there is an error, but then I realized that this might be 
> not safe as supposedly error() doesn't throw an exception and 
> therefore some destructors do not get called and some memory 
> may leak. Here is a simple example
>  
> extern "C" void foo() {
>     string str = "hello";
>     error("message");
> }
>  
> The memory allocated for str is leaked.
>  
> Did anyone think about this and find a way to work around the problem?
>  
> Thanks,
> Vadim
> 
>       [[alternative HTML version deleted]]
> 
> ______________________________________________
> [EMAIL PROTECTED] mailing list 
> https://www.stat.math.ethz.ch/mailman/listinfo> /r-help
> PLEASE 
> do read the posting guide! 
> http://www.R-project.org/posting-guide.html
> 
> ______________________________________________
> [EMAIL PROTECTED] mailing list 
> https://www.stat.math.ethz.ch/mailman/listinfo> /r-help
> PLEASE 
> do read the posting guide! 
> http://www.R-project.org/posting-guide.html
>

______________________________________________
[EMAIL PROTECTED] mailing list
https://www.stat.math.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html

Reply via email to