Saturday, July 26, 2008

Heap usage

I haven't posted in a while, due to lack of time and too much work, and I think this post has been rather overdue.
One of the things aspects of AIX's malloc (or for that matter any other operating system) is that if you free the memory you have allocated, it won't reflect in the svmon output. This is because malloc subsystem caches the memory, to be used for further malloc.
An easy way to see how much memory your application is using (the memory malloced by it, + the memory in the free pool maintained by the malloc subsystem) is to use the variable process_brk which is exported by libc.
The way I usually go about it is to use the dbx subcommand
(dbx) p &process_brk
This gives me the address to dump, which I dump using a command similar to the one below
(dbx) 0x12345678/3X
This will give an output of three words..
12345678 12345678 1
The first word signifies what was the brk value before the first malloc was done, and the second word tells you what was the brk value after the second allocation was done. The third word tells how many sbrk()s were done. Of course, this gives me a very good estimate of the total memory used by my program.
Another benifit of this thing is to check for heap/stack collision. To check whether there has been a heap stack collision in my 32-bit app, what I normally do is to dump the stack-pointer, and check whether the stack_pointer falls within the process_brk minimum and maximum limits.
Hope this helps.


Chris Cowan said...

Thanks for posting this. Been looking for two things:

- Is there any documentation on process_brk and other exported symbols anywhere?

- Do you know if there are *.h headers anywhere with the definitions, so that they can be more easily used in a prog?

Rajbir Bhattacharjee said...

Hey Chris,

Most malloc structures are internal. The header in which process_brk is defined is not shipped, and confidential to IBM.
That gives a lot of flexibility to IBM and they can change the structure and its size anytime.
If the header was shipped, then IBM wouldn't be able to change the structure in the future, as it promises binary compatibility, and there is no knowing how customers might use this structure.


Rajbir Bhattacharjee said...

Moreover, process_brk is undocumented.

shusi shusha said...

Thanks for the post!
Is it correct to say that the initial brk value should be in segment 2 (on a 32b process compiled without LDR_CNTRL=MAXDATA...)?
I have a 32b process which occasionally crashes on aix 6.1 64b with strange brk values (running malloc in dbx on the core) :

The Process Heap
Initial process brk value........ 0xd0237220
current process brk value........ 0xf08b3530
sbrk()s called by malloc......... 0

The Process Heap
Initial process brk value........ 0x00000000
current process brk value........ 0xd03e8fc0
sbrk()s called by malloc......... 4034840352

Rajbir Bhattacharjee said...

Shushi shusha,
Couple of things. LDR_CNTRL=MAXDATA doesn't need to be compiled. It is an environment variable and can be set.
The ALTERNATIVE is to compile with -bmaxdata (is it?, Its been a while I've worked on aix and haven't beein in touch).

If you ever get the initial break value as 0, (after at least one malloc has happened), Id be pretty confident in saying that someone overflowed something and overwrote process_brk. I'd actually try setting a hardware watchpoint on process_brk, with an automatic command "continue; trace", and log the output, and find out if anyone else other than malloc is also modifying it.