33

I'm trying to investigate the state of the C/C++ heap from within gdb on Linux amd64, is there a nice way to do this?

One approach I've tried is to "call mallinfo()" but unfortunately I can't then extract the values I want since gdb doesn't deal with the return value properly.

I'm not easily able to write a function to be compiled into the binary for the process I am attached to, so I can simply implement my own function to extract the values by calling mallinfo() in my own code this way. Is there perhaps a clever trick that will allow me to do this on-the-fly?

Another option could be to locate the heap and traverse the malloc headers / free list; I'd appreciate any pointers to where I could start in finding the location and layout of these.

I've been trying to Google and read around the problem for about 2 hours and I've learnt some fascinating stuff but still not found what I need.

trincot
  • 317,000
  • 35
  • 244
  • 286
Mike Tunnicliffe
  • 10,674
  • 3
  • 31
  • 46
  • 1
    What do you need to know about the state? What kind of statistics do you need to know? – Kaleb Pederson Apr 02 '10 at 02:46
  • Size of heap, amount used and amount free is a good start – Mike Tunnicliffe Apr 02 '10 at 04:04
  • What is gdb not doing properly? – leedm777 Apr 02 '10 at 23:52
  • Well I am only using my own definition of properly based on my requirements, which is to be able to de-reference the structure returned by "call mallinfo()" and look at the values of the members therein. – Mike Tunnicliffe Apr 03 '10 at 00:00
  • Sadly I think the situation is made more complicated because the inferior hasn't included malloc.h and "struct mallinfo" does not appear to be in the types list; maybe if it were then gdb would allow me to query its members. Instead I just get an integer value returned (possibly because the function definition is not included and it's defaulting to an int return type); this might be a pointer, but I don't know how to de-reference it (not a pointer into memory in the inferior). – Mike Tunnicliffe Apr 03 '10 at 00:01

2 Answers2

34

@fd - the RedHat bug had your answer.

The mallinfo function has been deprecated, and won't be updated. A true query stats API is TDB. Today, you have malloc_stats and malloc_info. I can't find any documentation on either one, but here's what they give you.

Is this close enough to what you need?

(gdb) call malloc_stats()
Arena 0:
system bytes     =     135168
in use bytes     =         96
Total (incl. mmap):
system bytes     =     135168
in use bytes     =         96
max mmap regions =          0
max mmap bytes   =          0

(gdb) call malloc_info(0, stdout)
<malloc version="1">
<heap nr="0">
<sizes>
<unsorted from="1228788" to="1229476" total="3917678" count="3221220448"/>
</sizes>
<total type="fast" count="0" size="0"/>
<total type="rest" count="3221220448" size="3917678"/>
<system type="current" size="135168"/>
<system type="max" size="135168"/>
<aspace type="total" size="135168"/>
<aspace type="mprotect" size="135168"/>
</heap>
<total type="fast" count="0" size="0"/>
<total type="rest" count="3221220448" size="3917678"/>
<system type="current" size="135168
/>
<system type="max" size="135168
/>
<aspace type="total" size="135168"/>
<aspace type="mprotect" size="135168"/>
</malloc>
leedm777
  • 23,444
  • 10
  • 58
  • 87
  • Good work, I found malloc_stats() last night and used it to pretty good effect in my testing earlier today. I also ran across sourceware's glibc wiki which pointed to Ulrich Drepper's livejournal with this post - http://udrepper.livejournal.com/20948.html - from April '09 describing the replacement to mallinfo (amoungst other things) but I've yet to try it out. Thanks for posting the output, looks very interesting. +1 – Mike Tunnicliffe Apr 07 '10 at 19:25
  • By the way, did you find any doc for malloc_info()? Does the first argument describe the arena number? I see the in the output, and in my test malloc_stats() shows stats for a number of arenas (aside: mallinfo() also seems to be limited in that it only shows information from the zero-th arena, which is why my tests of it didn't match the memory usage I saw reported by top; also, no single arena statistic grew enough to hit the bug I referenced before). – Mike Tunnicliffe Apr 07 '10 at 19:30
  • I can't find docs for malloc_info(). According to the source, `if (options != 0) return EINVAL` - http://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=558e8bab0ab3808ec9f5b569ca62863ef4651b27;hb=HEAD#l6323. Looks like it iterates through all arenas. – leedm777 Apr 08 '10 at 04:56
  • 2
    My running processes stdout was redirected to some log file. so `call malloc_stats()` didn't print out on console, but rather that log file. Took me almost an hour to figure that out. – JamesWebbTelescopeAlien Feb 20 '19 at 02:26
6

If you can change the code:

#include <malloc.h>
#include <stdio.h>

void dumpMallinfo(void) {
  struct mallinfo m = mallinfo();
  printf("uordblks = %d\nfordblks = %d\n", m.uordblks, m.fordblks);
}

In GDB, you can call dumpMallinfo().

leedm777
  • 23,444
  • 10
  • 58
  • 87
  • As I stated in the question, I can't, however this is a useful technique. +1 (this was one of the approaches the 2 hours of Googling revealed) – Mike Tunnicliffe Apr 03 '10 at 01:27
  • 1
    Found a useful bit of info regarding mallinfo(); it doesn't appear to be 64-bit ready. The structure returned, being composed of int members, does not handle byte sizes above 4GB. I haven't found any evidence of a fix for this, although I found both a Debian and a RedHat bug report both closed as NOTABUG/WONTFIX. – Mike Tunnicliffe Apr 06 '10 at 22:44
  • To reiterate my comment on dave's other answer below: mallinfo() also seems to be limited in that it only shows information from the zero-th arena, which is why my tests of it didn't match the memory usage I saw reported by top; also, no single arena statistic grew enough to hit the bug I mentioned before. malloc_stats() showed information from all the arenas. – Mike Tunnicliffe Apr 07 '10 at 19:31