On Tue, 20 Apr 2010, Simon Urbanek wrote:
On Apr 19, 2010, at 1:22 PM, Seth Falcon wrote:
On 4/19/10 8:59 AM, Simon Urbanek wrote:
On Apr 19, 2010, at 10:39 AM, Melissa Jane Hubisz wrote:
Hello,
The Writing R extensions manual section 6.1.1 describes the transient
memory allocation function R_alloc, and states that memory allocated
by R_alloc is automatically freed after the .C or .Call function is
completed. However, based on my understanding of R's memory handling,
as well as some test functions I have written, I suspect that this is
not quite accurate. If the .Call function returns an external pointer
to something created with R_alloc, then this object seems to stick
around after the .Call function is completed, and is subject to
garbage collection once the external pointer object is removed.
Yes, because the regular rules for the lifetime of an R object apply
since it is in fact an R object. It is subject to garbage collection
so if you assign it anywhere its lifetime will be tied to that object
(in your example EXTPTRSXP).
I may be misunderstanding the question, but I think the answer is actually that
it is *not* safe to put memory allocated via R_alloc into the external pointer
address of an EXTPTRSXP.
Here's what I think Melissa is doing:
SEXP make_test_xp(SEXP s)
{
SEXP ans;
const char *s0 = CHAR(STRING_ELT(s, 0));
char *buf = (char *)R_alloc(strlen(s0) + 1, sizeof(char));
memcpy(buf, s0, strlen(s0) + 1);
ans = R_MakeExternalPtr(buf, R_NilValue, R_NilValue);
return ans;
}
The memory allocated by R_alloc is "released" at the end of the .Call via
vmaxset(vmax). Using R_alloc in this way will lead to memory corruption (it does for me
when I made a simple test case).
Can you elaborate on that? (It's really tricky to test this since you cannot
attach a finalizer to the allocated memory).
AFAICT the R_alloc allocates a regular R vector (raw or real depending on size)
so the usual R object rules apply. Then it is attached to the VStack. If you
also assign it to any other object accessible from the GC roots (before the
VStack goes away) then even removing the VStack entry won't cause de-allocation
because it will be flagged from the other root at mark time so it won't be
garbage collected. VStack is not released blindly it is simply pruned and left
to garbage collection to decide whether to release the objects or not.
But R_alloc returns the pointer to the data associated with the SEXPR
that goes in the vstack, and there is no official way to get from that
data pointer to the SEXPR. So the allocation can't be GC protected by
anything done in the code that calls R_alloc.
In any case the implementation of R_alloc is not intended to be public
and could change.
luke
That said, the lesson to Melissa is that you can simply allocate a raw vector
with the same effect - there is no need to use R_alloc() in her case (is user
code PROTECTing is sort of equivalent to the VStack used internally).
Cheers,
Simon
For memory that really is external (not SEXP), then you should instead use
Calloc and register a finalizer for the external pointer that will do any
required cleanup and then call Free.
If instead you want to have an externally managed SEXP, you could put it in the
protected slot of the external pointer, but then you should allocate it using
standard R allocation functions.
+ seth
--
Seth Falcon | @sfalcon | http://userprimary.net/
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
--
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: l...@stat.uiowa.edu
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel