Recently I came across a core dump related to jemalloc:
#0 extent_arena_ind_get (extent=0x0) at include/jemalloc/internal/extent_inlines.h:40
#1 je_tcache_bin_flush_small (tsd=tsd@entry=0x7ffff7f717f8, tcache=tcache@entry=0x7ffff7f719e8,
tbin=tbin@entry=0x7ffff7f71a70, binind=binind@entry=5, rem=<optimized out>) at src/tcache.c:159
#2 0x00007ffff356b97b in je_tcache_event_hard (tsd=tsd@entry=0x7ffff7f717f8,
tcache=tcache@entry=0x7ffff7f719e8) at src/tcache.c:55
#3 0x00007ffff3512d49 in tcache_event (tcache=<optimized out>, tsd=<optimized out>)
at include/jemalloc/internal/tcache_inlines.h:37
#4 tcache_dalloc_large (slow_path=<optimized out>, binind=<optimized out>, ptr=<optimized out>,
tcache=<optimized out>, tsd=<optimized out>) at include/jemalloc/internal/tcache_inlines.h:212
#5 arena_dalloc_large (slow_path=<optimized out>, szind=<optimized out>, tcache=<optimized out>,
ptr=<optimized out>, tsdn=<optimized out>) at include/jemalloc/internal/arena_inlines_b.h:276
#6 arena_dalloc (slow_path=<optimized out>, alloc_ctx=<optimized out>, tcache=<optimized out>,
ptr=<optimized out>, tsdn=<optimized out>) at include/jemalloc/internal/arena_inlines_b.h:323
#7 idalloctm (slow_path=<optimized out>, is_internal=<optimized out>, alloc_ctx=<optimized out>,
tcache=<optimized out>, ptr=<optimized out>, tsdn=<optimized out>)
at include/jemalloc/internal/jemalloc_internal_inlines_c.h:118
#8 ifree (slow_path=<optimized out>, tcache=<optimized out>, ptr=<optimized out>,
tsd=<optimized out>) at src/jemalloc.c:2589
#9 je_free_default (ptr=0x7fff2ccf53c0) at src/jemalloc.c:2799
The Sanitizers helped me to find the root cause: a classical “double-free” memory issue. One thing should be noticed is the Sanitizers
and jemalloc
can’t be used simultaneously because they both intercept memory allocation/free functions. Check following code:
# cat memory-leak.c
#include <stdlib.h>
void *p;
int main() {
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
Build with both Sanitizers
and jemalloc
:
# gcc -fsanitize=address -g memory-leak.c -L`jemalloc-config --libdir` -Wl,-rpath,`jemalloc-config --libdir` -ljemalloc `jemalloc-config --libs`
# ldd a.out
linux-vdso.so.1 (0x00007ffdb85a6000)
libasan.so.6 => /usr/lib/libasan.so.6 (0x00007ffb04605000)
libjemalloc.so.2 => /usr/lib/libjemalloc.so.2 (0x00007ffb04362000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007ffb0421d000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007ffb03fb4000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007ffb03fae000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007ffb03f8d000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007ffb03dc5000)
librt.so.1 => /usr/lib64/../lib64/librt.so.1 (0x00007ffb03dba000)
libgcc_s.so.1 => /usr/lib64/../lib64/libgcc_s.so.1 (0x00007ffb03da0000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007ffb04fdc000)
Use gdb
to debug the program:
......
Breakpoint 2, 0x00007ffff76a90a4 in malloc () from /usr/lib/libasan.so.6
(gdb) bt
#0 0x00007ffff76a90a4 in malloc () from /usr/lib/libasan.so.6
#1 0x0000555555555183 in main () at memory-leak.c:4
......
The program will use functions from Sanitizers
instead of jemalloc
.