Skip to content
Advertisement

Using pmap and gdb to find native memory leak

I am debugging a native memory leak in java application. The rss is growing 1GB/day while heap showing no increase. On comparing the output of pmap over time, I see multiple anon blocks getting added either at the top of heap or between two native libraries.

JavaScript
  1. Can I say the memory increase between, say sssd_pac_plugin.so and librmi.so, is due to any one of them? Is this memory allocations contiguous? https://i.stack.imgur.com/G1duY.jpg

  2. There are a lot of new memory block created, ranging from 126MB to 1MB(100 small 1MB block attached image for reference) at the top of the heap (address: 00007fc940000000 and greater). Do they signify some memory leak or just created for each new thread.

enter image description here

  1. To see data in these blocks, I tried the below snippet, but I always get no strings from it. It is all in binary which I cant interpret. Is there a way to convert it to strings? Or map to any thread/library or anything i can work with.
JavaScript

One more observation is that many of the new blocks and old block get increased to aprox 60-65MB. The number of these blocks increases a lot with time. Contributing the most to rss increase. https://i.stack.imgur.com/xueC8.png https://i.stack.imgur.com/hwbAb.jpg

I tried libtcmalloc and profilers too, the major issue is in the production environment where i cannot use these. On dev instance the leak is not that significant so profiler’s output cannot be verified.

Advertisement

Answer

A very basic approach: you could try looking at who is calling mmap (and not munmap).

  • attach to the process
  • set breakpoint on mmap, with commands to print arguments and backtrace (maybe 5 frames) and continue
  • similar thing for munmap
  • redirect output
  • let it run for a day
  • detach
  • match mmaps with munmaps in the output

With pmap periodically running on the side, you may be able to match newer anon regions with mmap backtraces (might need playing around with frame count).


There is already this nice little article LINUX GDB: IDENTIFY MEMORY LEAKS to get you started.

Note:

  • you are looking for mmap and munmap, not malloc and free
  • you will have to find out the offset of the return from mmap
  • I have not tried the script from the article but I think it would do what the article claims

Finding mmap return instruction offset (from start of mmap): Just fire up gdb with any executable on the same host

JavaScript

Note the return instruction here:

JavaScript

So, on my machine, the second breakpoint would have to be set at (mmap+76).

Once you determine this offset, you can verify this offset by attaching to your target process and disassembling what is at that offset. E.g. taking my current shell as my target process:

JavaScript

I’m not very sure hbreak is required, plain old break might work as well.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement