[Rd] garbage collection, "preserved" variables, and different outcome depending on "--verbose" or not

Duncan Murdoch murdoch at stats.uwo.ca
Sun Jul 20 15:53:08 CEST 2008


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