Dear R .Call() insiders,

Can someone enlighten me how to properly finalize external pointers in C code 
(R-2.5.1 win)? What is the relation between R_ClearExternalPtr and the 
finalizer set in R_RegisterCFinalizer?

I succeeded registering a finalizer that works when an R object containing an 
external pointer is garbage collected. However, I have some difficulties 
figuring out how to do that in an explicit closing function. 

I observed that 
- calling R_ClearExternalPtr does not trigger the finalizer and is dangerous 
because it removes the pointer before the finalizer needs it at 
garbage-collection-time (no finalization = memory leak)
- calling the finalizer directly ensures finalization but now the finalizer is 
called twice (once again at garbage collection time, and I did not find 
documentation how to unregister the finalizer)
- It works to delete the SEXP external pointer object but only if not calling 
R_ClearExternalPtr (but why then do we need it?) Furthermore it is unfortunate 
to delay freeing the external pointers memory if I know during runtime that it 
can be done immediately.

Shouldn't R_ClearExternalPtr call the finalizer and then unregister it? (this 
would also work when removing the SEXP external pointer object is difficult 
because it was handed over to the closing function directly as a parameter)

Best regards


Jens Oehlschlägel


// C-code

static void rindex_finalize(SEXP extPtr){
  pINT ptr = R_ExternalPtrAddr(extPtr);
  if(ptr){
    Free(ptr);
    Rprintf("finalized\n");
  }else{
    Rprintf("nothing to finalize\n");
  }
  return;
}


SEXP rindex_open(
  SEXP Sn
){
  int i,n = INTEGER(Sn)[0];
  pINT ptr = Calloc(sizeof(INT)*n, INT);
  SEXP extPtr, ret;
  for (i=0;i<n;i++){
    ptr[i] = i;
  }
  extPtr = R_MakeExternalPtr(ptr, install("Rindex_extPtr"), R_NilValue);
  R_RegisterCFinalizer(extPtr, rindex_finalize);

  PROTECT(ret = allocVector(VECSXP, 1));
  SET_VECTOR_ELT(ret,0,extPtr);
  UNPROTECT(1);
  return ret;
}

SEXP rindex_close(
  SEXP obj
){
  int i, n= 10;
  SEXP ret, extPtr=VECTOR_ELT(obj, 0);
  pINT p, ptr = R_ExternalPtrAddr(extPtr);

  PROTECT(ret = allocVector(INTSXP, n));
  p = INTEGER(ret);
  for (i=0;i<n;i++){
    Rprintf("ptri=%d\n",ptr[i]);
    p[i] = ptr[i];
  }

  /* this does finalize immediately but at next garbage collection again
  rindex_finalize(extPtr);
  */

  /* this must not called otherwise the pointer is gone at garbage collection 
time
  R_ClearExternalPtr(extPtr);
  */

  /* this triggers the finalizer but only at next garbage collection */
  SET_VECTOR_ELT(obj,0,R_NilValue);

  UNPROTECT(1);
  return ret;
}


# R-Code
initRindex <- function(){
  dyn.load(file.path(.libPaths(), "rindex", "libs", paste("rindex", 
.Platform$dynlib.ext, sep = "")))
}

doneRindex <- function(){
  dyn.unload(file.path(.libPaths(), "rindex", "libs", paste("rindex", 
.Platform$dynlib.ext, sep = "")))
}


openRindex <- function(n=10){
  .Call("rindex_open", as.integer(n))
}

closeRindex <- function(extPtr){
  .Call("rindex_close", extPtr)
}

if (FALSE){
  # now try it
  require(rindex)

  initRindex()

  extPtr <- openRindex()
  extPtr
  extPtr2 <- closeRindex(extPtr)
  extPtr2
  gc()

  extPtr <- openRindex()
  extPtr2 <- extPtr
  extPtr2
  rm(extPtr)
  gc()
  extPtr2
  rm(extPtr2)
  gc()
  extPtr2

  doneRindex()
}


> version
               _                           
platform       i386-pc-mingw32             
arch           i386                        
os             mingw32                     
system         i386, mingw32               
status                                     
major          2                           
minor          5.1                         
year           2007                        
month          06                          
day            27                          
svn rev        42083                       
language       R                           
version.string R version 2.5.1 (2007-06-27)



-- 
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kanns mit allen: http://www.gmx.net/de/go/multimessenger

______________________________________________
R-help@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to