Skip to content
Prev 41263 / 63424 Next

External pointers and an apparent memory leak

James, 

Works for me!

In a file, 'test.c', I have:

void h5R_allocate_finalizer(SEXP eptr) {
    char* vector = (char*) R_ExternalPtrAddr(eptr);
    free(vector);
    printf("memory freed at address %lu\n", (long unsigned) vector);
    R_ClearExternalPtr(eptr);
}

SEXP h5R_allocate(SEXP size) {
    int i = INTEGER(size)[0];
    char* vector = (char*) malloc(i*sizeof(char));
    printf("memory allocated at address %lu\n", (long unsigned) vector);
    SEXP e_ptr = R_MakeExternalPtr(vector, R_NilValue, R_NilValue);
    R_RegisterCFinalizerEx(e_ptr, h5R_allocate_finalizer, TRUE);
    return e_ptr;
}

I generated the shared library with R CMD SHLIB. Then, at the R prompt:

R> dyn.load('test.so')
R> system(paste('ps -eo pid,vsz | grep', Sys.getpid()))
10961  77160
R> v <- .Call('h5R_allocate', as.integer(2^24))
memory allocated at address 140127935406096
R> system(paste('ps -eo pid,vsz | grep', Sys.getpid()))
10961  93548
R> rm(v); gc()
memory freed at address 140127935406096
         used (Mb) gc trigger (Mb) max used (Mb)
Ncells 132769  7.1     350000 18.7   350000 18.7
Vcells 129312  1.0     786432  6.0   555216  4.3
R> system(paste('ps -eo pid,vsz | grep', Sys.getpid()))
10961  77160

It appears that the external pointer is behaving as expected. However, I
did find that gc() may not immediately collect the removed object 'v'.
Sometimes it took more than one call. In any case, the memory was freed
when R exits.

Best,
Matt
On Wed, 2011-09-14 at 21:21 +0000, James Bullard wrote: