Error messages and C
On Fri, 2004-08-20 at 12:04, Thomas Lumley wrote:
On Fri, 20 Aug 2004, Ross Boylan wrote:
I am calling a C (C++ really) function via the .C interface. Sometimes when things go wrong I want to return an error message. 1. R provides C functions error and warning which look about right. But exactly how does this exit, and in particular what happens with cleaning up, calling C++ destructors, and unwinding the stack? Will I get memory leaks?
Memory handled by R will be reclaimed properly (ie R_alloc, but not Calloc). C++ destructors will not be called -- you have to do that yourself either before calling error()
That's not hard in my case, so that's what I'm doing.
or in subsequent cleanup code that you call from R (perhaps triggered by on.exit()).
That would be tricky, since the location of the objects to be destroyed is only known inside my original function. Of course, I could use global variables...
R does have a finalizer mechanism that you could use. I have never tried this but there are some notes at http://www.stat.uiowa.edu/~luke/R/references/weakfinex.html This allows C or R functions to be called by the garbage collector when an object is disposed of. You can then put an object on the R heap so that when R tidies this object up it will call your C++ destructors.
The weak references cleaned up are R objects, and my stuff is mostly non-R objects. I see two possible ways to get this to work: 1) Create some kind of dummy R object with a finalizer that cleans up my C++ objects. 2) Hook the C++ object creation facilities (via new) into R. Either approach is complex, possibly not doable, and probably inefficient. Fortunately, I don't need this.
2. Before I discovered those functions, I looked at passing in a character vector as an argument, char ** p in the C code. Exactly how do I use these things? Am I supposed to allocate a string and stuff the pointer in the function argument? Or should I assume *p points to valid space (how much?) and fill it in?
If you think of p as a vector of strings (ie char *p[]) then it corresponds to whatever strings you passed in from R. You can modify these in place, possibly making them shorter. So if you need 80 characters of error message, pass in a string of length at least 80.
If space permits, is this just an ordinary, C-style null terminated string? Or does R have some notion of the string length which is unaffected by what I stuff in it?
If you want to allocate more memory you need to do this through R (either R_alloc or the Rinternals functions). Using malloc() and stuffing the result in, say, p[1], will cause a memory leak since you won't be able to find it and free it.
So if I overwrite p[0], for example, the R garbage collector will know to clean up the old string that was pointed to from that location?
-thomas
Thanks for the info.
Ross Boylan wk: (415) 502-4031 530 Parnassus Avenue (Library) rm 115-4 ross at biostat.ucsf.edu Dept of Epidemiology and Biostatistics fax: (415) 476-9856 University of California, San Francisco San Francisco, CA 94143-0840 hm: (415) 550-1062