From mjhubisz at gmail.com  Tue Apr 20 15:24:05 2010
From: mjhubisz at gmail.com (Melissa Jane Hubisz)
Date: Tue, 20 Apr 2010 09:24:05 -0400
Subject: [Rd] transient memory allocation and external pointers
In-Reply-To: <4BCC9150.10700@userprimary.net>
References: <u2z3aa2e7491004190739o1d6bcffbi997ac207d51865e0@mail.gmail.com> 
	<80F422FF-8907-4F2F-9AA3-A40423629C61@r-project.org>
	<4BCC9150.10700@userprimary.net>
Message-ID: <r2m3aa2e7491004200624s2f1a0a28ofb5781dad86ee84d@mail.gmail.com>

Thanks for the responses.  Seth's example is indeed what I was trying
(hoping) to do, it seems to work on my system fine (ubuntu x86_64, R
2.10.1).  But if it doesn't work for him, then that definitely answers
my question.  I guess I'll have to go the Calloc/Free route.
Thanks,
Melissa

On Mon, Apr 19, 2010 at 1:22 PM, Seth Falcon <seth at userprimary.net> 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).
>
> 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 at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] transient memory allocation and external pointers
Melissa Jane Hubisz