[Rd] garbage collection, "preserved" variables, and different outcome depending on "--verbose" or not
Laurent Gautier
lgautier at gmail.com
Sun Jul 20 16:02:57 CEST 2008
I tripped on that while crafting the example.
The problem still exists when moving the "releases" in the middle,
and removing the last "release".
#include <R.h>
#include <Rdefines.h>
SEXP createObject(void)
{
SEXP x_R;
int len_x = 1000000;
PROTECT(x_R = allocVector(REALSXP, len_x));
Rprintf("Created 'x' at %p\n", x_R);
Rprintf(" (mode is %i, length is %i)\n", TYPEOF(x_R), LENGTH(x_R));
Rprintf(" (first element is %d)\n", REAL(x_R)[0]);
R_PreserveObject(x_R);
UNPROTECT(1);
return x_R;
}
void printObject(SEXP sexp)
{
Rprintf("object at %p\n", sexp);
Rprintf(" (mode is %i, length is %i, named is %i)\n",
TYPEOF(sexp), LENGTH(sexp), NAMED(sexp));
}
SEXP lostobject(SEXP n_R)
{
/*
* This function will:
* 1- create a numerical vector "x" and "preserve it"
* 2- make call "list(x)"
* 3- return "x" to R
*/
SEXP x_R;
int i;
int n = INTEGER(n_R)[0];
/* Create a numerical vector "x_R" */
for (i=0; i<n; i++) {
x_R = createObject();
printObject(x_R);
R_ReleaseObject(x_R);
R_gc();
}
x_R = createObject();
printObject(x_R);
R_gc();
Rprintf("Returning 'x' at %p\n", x_R);
Rprintf(" (first element is %d)\n", REAL(x_R)[0]);
return x_R;
}
2008/7/20 Duncan Murdoch <murdoch at stats.uwo.ca>:
> On 20/07/2008 9:01 AM, Laurent Gautier wrote:
>>
>> Dear list,
>>
>> While trying to identify the root of a problem I am having with
>> garbage collected variables,
>> I have come across the following oddity: depending on whether --verbose is
>> set
>> or not, I obtain different results.
>
> You are working with variables without protecting them, so you just get
> lucky whenever the code works.
>
> More below...
>
>>
>> I have made a small standalone example to demonstrate it.
>> The example is very artificial, but I had a hard time reproducing
>> reliably the problem.
>>
>> So when I do: (the content of test.R is at the end of this email)
>>
>> R --no-save < test.R
>>
>> [The two last lines of the output are:]
>>>
>>> x[1:3]
>>
>> [1] 0 0 0
>>
>> while with
>>
>> R --verbose --no-save < test.R
>>
>> [The two last lines of the output are:]
>>>
>>> x[1:3]
>>
>> [1] 3.733188e-317 3.137345e-317 3.137345e-317
>>
>>
>> The C code is compiled with:
>> R CMD SHLIB test_lostobject.c
>>
>>
>>> sessionInfo()
>>
>> R version 2.7.1 Patched (2008-07-19 r46081)
>> x86_64-unknown-linux-gnu
>>
>> locale:
>>
>> LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=C;LC_MESSAGES=en_US.UTF-8;LC_PAPER=en_US.UTF-8;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=en_US.UTF-8;LC_IDENTIFICATION=C
>>
>> attached base packages:
>> [1] stats graphics grDevices utils datasets methods base
>>
>>
>>
>> ### -- file test.R
>>
>> dyn.load("test_lostobject.so")
>>
>> x = .Call("lostobject", as.integer(5))
>>
>> x[1:3]
>>
>>
>> ### ---
>>
>> ###--- file lostobject.c
>>
>> #include <R.h>
>> #include <Rdefines.h>
>>
>>
>>
>> SEXP createObject(void)
>> {
>> SEXP x_R;
>> int len_x = 1000000;
>> PROTECT(x_R = allocVector(REALSXP, len_x));
>> Rprintf("Created 'x' at %p\n", x_R);
>> Rprintf(" (mode is %i, length is %i)\n", TYPEOF(x_R), LENGTH(x_R));
>> Rprintf(" (first element is %d)\n", REAL(x_R)[0]);
>> R_PreserveObject(x_R);
>> UNPROTECT(1);
>> return x_R;
>> }
>>
>> void printObject(SEXP sexp)
>> {
>> Rprintf("object at %p\n", sexp);
>> Rprintf(" (mode is %i, length is %i, named is %i)\n",
>> TYPEOF(sexp), LENGTH(sexp), NAMED(sexp));
>> }
>>
>> SEXP lostobject(SEXP n_R)
>> {
>> /*
>> * This function will:
>> * 1- create a numerical vector "x" and "preserve it"
>> * 2- make call "list(x)"
>> * 3- return "x" to R
>> */
>>
>>
>> SEXP x_R;
>> int i;
>>
>> int n = INTEGER(n_R)[0];
>>
>> /* Create a numerical vector "x_R" */
>>
>> for (i=0; i<n; i++) {
>> x_R = createObject();
>> R_ReleaseObject(x_R);
>
> At this point, the variable is unprotected, i.e. you have declared that its
> memory is free for the taking. You should not try to do anything with it.
> printObject calls several functions, and one of those may have overwritten
> the memory. It's not surprising that different flags (--verbose or not)
> result in different behaviour.
>
>> printObject(x_R);
>> R_gc();
>> }
>>
>> x_R = createObject();
>> printObject(x_R);
>> R_gc();
>> R_ReleaseObject(x_R);
>
> Same thing here. x_R is unprotected now, so you shouldn't use it.
>
> Duncan Murdoch
>
>> Rprintf("Returning 'x' at %p\n", x_R);
>> Rprintf(" (first element is %d)\n", REAL(x_R)[0]);
>> return x_R;
>> }
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>
More information about the R-devel
mailing list