Laurent Gautier
2008-Jul-20 13:01 UTC
[Rd] garbage collection, "preserved" variables, and different outcome depending on "--verbose" or not
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. 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); printObject(x_R); R_gc(); } x_R = createObject(); printObject(x_R); R_gc(); R_ReleaseObject(x_R); Rprintf("Returning 'x' at %p\n", x_R); Rprintf(" (first element is %d)\n", REAL(x_R)[0]); return x_R; }
Duncan Murdoch
2008-Jul-20 13:53 UTC
[Rd] garbage collection, "preserved" variables, and different outcome depending on "--verbose" or not
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