Skip to content
Prev 41265 / 63424 Next

External pointers and an apparent memory leak

Hi Simon, Matt

First, thank you for the help. My memory is still growing and it is clear that I'm removing the things I am allocating - potentially it is just Linux not giving back the memory until another process needs it, but it definitely doesn't behave that way when I allocate directly within R. To be a better poster:

#> system("uname -a")
#Linux mp-f020.nanofluidics.com 2.6.32-30-server #59-Ubuntu SMP Tue Mar 1 22:46:09 UTC 2011 x86_64 #GNU/Linux

#> sessionInfo()
#R version 2.13.1 Patched (2011-09-13 r57007)
#Platform: x86_64-unknown-linux-gnu (64-bit)

Here, if you look at the successive allocations you'll see that by the end I have started to grow my memory and, at least w.r.t. the ps method of memory profiling, I'm leaking memory.
18937 147828  0.1
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 213919 11.5     407500 21.8   213919 11.5
Vcells 168725  1.3     786432  6.0   168725  1.3
18937 147828  0.1
+   .Call("h5R_allocate_meg")
+ })
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 213920 11.5     467875   25   213920 11.5
Vcells 168725  1.3     786432    6   168725  1.3
18937 147828  0.1
+   .Call("h5R_allocate_k")
+ })
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 213920 11.5     818163 43.7   213920 11.5
Vcells 168725  1.3     895968  6.9   168725  1.3
18937 271860  0.9
+   .Call("h5R_allocate_k")
+ })
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 213920 11.5     785114 42.0   213920 11.5
Vcells 168725  1.3    1582479 12.1   168725  1.3
18937 1409568  7.8

I have redone the examples to better demonstrate the issue I am seeing. Below is the C code:

#include <hdf5.h>
#include <Rinternals.h>    
#include <R.h>
void h5R_allocate_finalizer(SEXP eptr) {
    char* vector = R_ExternalPtrAddr(eptr);
    Free(vector);
    R_ClearExternalPtr(eptr);
}
SEXP h5R_allocate_meg() {
    char* vector = (char*) Calloc(1048576, char);
    for (int j = 0; j < 1048576; j++) {
    	vector[j] = 'c';
    }
    SEXP e_ptr = R_MakeExternalPtr(vector, R_NilValue, R_NilValue); 
    PROTECT(e_ptr);
    R_RegisterCFinalizerEx(e_ptr, h5R_allocate_finalizer, TRUE);
    UNPROTECT(1);
    return e_ptr;
}
SEXP h5R_allocate_k() {
    char* vector = (char*) Calloc(1024, char);
    for (int j = 0; j < 1024; j++) {
    	vector[j] = 'c';
    }
    SEXP e_ptr = R_MakeExternalPtr(vector, R_NilValue, R_NilValue); 
    PROTECT(e_ptr);
    R_RegisterCFinalizerEx(e_ptr, h5R_allocate_finalizer, TRUE);
    UNPROTECT(1);
    return e_ptr;
}
SEXP h5R_allocate_gig() {
    char* vector = (char*) Calloc(1073741824, char);
    for (int j = 0; j < 1073741824; j++) {
    	vector[j] = 'c';
    }
    SEXP e_ptr = R_MakeExternalPtr(vector, R_NilValue, R_NilValue); 
    PROTECT(e_ptr);
    R_RegisterCFinalizerEx(e_ptr, h5R_allocate_finalizer, TRUE);
    UNPROTECT(1);
    return e_ptr;
}


Finally, when I use valgrind on the test script, I see:

==22098== 135,792 bytes in 69 blocks are possibly lost in loss record 1,832 of 1,858
==22098==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==22098==    by 0x4F5D799: GetNewPage (memory.c:786)
==22098==    by 0x4F5EE6F: Rf_allocVector (memory.c:2330)
==22098==    by 0x4F6007F: R_MakeWeakRefC (memory.c:1198)
==22098==    by 0xE01BACF: h5R_allocate_k (h5_debug.c:33)
==22098==    by 0x4EE17E4: do_dotcall (dotcode.c:837)
==22098==    by 0x4F18D02: Rf_eval (eval.c:508)
==22098==    by 0x4F1A7FD: do_begin (eval.c:1420)
==22098==    by 0x4F18B1A: Rf_eval (eval.c:482)
==22098==    by 0x4F1B7FC: Rf_applyClosure (eval.c:838)
==22098==    by 0x4F189F7: Rf_eval (eval.c:526)
==22098==    by 0x4E6F3D8: do_lapply (apply.c:72)

Thanks for any help!

jim