index   headlines   <<previous   next>> 

Leak Checker
Developer Release Notes
BeOS Release 4.5

The Intel-only Leck Checker is a memory-checking utility that's built into libroot.so. The Leck Checker checks new and malloc() allocations, and periodically prints (to the Terminal) memory-use statistics.  Not only does the Leck Checker help you find memory leaks, it can also help you find inefficient parts of your code.  The utility isn't polished yet—and you need to understand what you're doing when you use it.


Enabling the Leak Checker

To enable the Leck Checker, you define these two environment variables in a Terminal window:

export MALLOC_LEAK_CHECK=true
export NEW_LEAK_CHECK=true

You then launch your application from the same Terminal.  While the Leck Checker is running, your app's memory allocations will take a bit more time than usual.  Note that the performance of other apps (i.e. any app that isn't launched from the Terminal that has the Leck Checker variables defined) isn't affected.

To turn off the Leck Checker, simply close the Terminal.  (This will, of course, kill the app that you're checking.)


Leak Checker statistics

While it's running, the Leck Checker periodically prints two tables of statistics to the Terminal: One for new calls, and a separate table for malloc().  Looking at a malloc() table, we first see this header:

1195 current malloc allocations, 50195 bytes, sorted by count: ============

This says that there are 1195 outstanding malloc() allocations— in other words, 1195 chunks of malloc()'d memory are yet to be freed()'d.  The "50195 bytes" is the size of the outstanding memory. The "sorted by count:" tells you how the table, which follows the header, is sorted, and the end of the line ("============") is there simply to catch your eye.  The lines at the end also help distinguish the malloc() header from the new header:

134 current new allocations, 15268 bytes, sorted by count: ------------

After the header, the table itself is printed:

call: ec92fdc9, ec680c4a, 800108af, ..., 168 calls, size 1256
call: ec92fdc9, ec63ad75, ec6cdc3b, ..., 145 calls, size 1470
call: ec92fdc9, ec6808b2, ec680ae0, ..., 120 calls, size 1315              

You'll see as many as 20 lines in the table. Each line gives a series of three addresses that form a calling chain (or stack crawl).  For example, the first line in the example says that malloc() was called by the function located at ec92fdc9, which was called by ec680c4a, which was called by 800108af, and so on. (The elided section shown in the example above also contains addresses, but we'll ignore them for now.)  The "168 calls" and "size 1256" at the end of the line mean that this chain of three function calls called malloc() 168 times for a total of 1256 bytes of memory allocated. By printing out the calling chain, Leak Checker helps you find suspicious code paths. 

(The new table is formatted in the same way as the malloc() table.)

Note that bdb understands the Leak Checker table: Copy a line from the Leak Checker table and paste it into bdb's Window > Show Address... panel.  The debugger will display the stack crawl in a stack crawl window.

When your application quits a final list is printed—these are definite leaks.

app exiting, final list:
5 current malloc allocations, 3559 bytes, sorted by count: ============
17 current new allocations, 920 bytes, sorted by count: ------------       

Leak Checker will also tell you if there's an attempt to use free() on memory that was allocated with new, or if malloc()'d memory is delete'd.

Note that the leakchecker checks every allocation in your app— including allocations made by the Be libraries.  Because of this, you might see leaks that are caused by Be code, rather than your own.


Fine-tuning Leak Checker

  • Setting the frequency

    You can set the frequency with which the leakchecker statistics are printed by setting these variables (in the Terminal):

    export MALLOC_LEAK_CHECK_DUMP_PERIOD=1000
    export NEW_LEAK_CHECK_DUMP_PERIOD=1000

    Here, we've set the checker to print the malloc() table after every 1000 malloc() calls, and the new new table after every 1000 new calls.

  • Setting the sort order

    You can change the table's sorting order to the total size of allocations rather than the number of allocations by setting these variables:

    export MALLOC_LEAK_CHECK_SORT_BY_SIZE = true
    export NEW_LEAK_CHECK_SORT_BY_SIZE = true

  • Setting the comparison depth

    Remember when we brushed over the elided section of the calling chain example? That section contains as many as seven addresses that are also part of the calling chain—but, by default, they're not as siginificant as the first three...

    By default, the Leak Checker looks at only the first three frames of a calling chain when comparing it to other chains in the table.  When it sees two chains that have the same first three addresses, it considers them to be the same (for the purposes of counting). Although the final seven addresses aren't completely arbitrary, they don't necessarily outline the path of every calling chain in that "bin".

    You can change this "comparison depth" through these variables:

    export MALLOC_LEAK_CHECK_COMPARE_LEVEL = 5
    export NEW_LEAK_CHECK_COMPARE_LEVEL = 4

    By setting the value lower, Leak Checker, fewer functions in the chain are common to the entire chain.  By setting it higher, more of the functions are common to the entire chain.  Finding the right comparison depth is a subtle point, but it can be important.


    Leak Checking while Debugging

    If you want to check for leaks while you're using a high-level debugger (such as bdb), you should turn on leak checking from your code rather than by setting the environment variables.  To do this, you call these functions from main():

    extern"C" void SetNewLeakChecking(bool);
    extern"C" void SetMallocLeakChecking(bool);



     index   headlines   <<previous   next>> 

    BeOS Release 4.1


    Copyright © 1999 Be, Inc.  All rights reserved.