Memory leaks are one of our main areas of interest. Since the average user will only notice them by growing memory usage, we don't see as many bug reports on them as we'd like. This is some information about how to hunt down those leaks. The Mac OS X Developer Tools include a very useful program for leak detection. Here's how you can use it:
- Get a fresh WebKit build, ideally a Debug build as this turns off the various custom allocators in WebKit.
Set the MallocStackLogging environment variable to YES (in bash,
export MallocStackLogging=YES, in tcsh,
setenv MallocStackLogging YES).
Run Safari using
- Browse around a little.
From the command line, run
At this point, if you've found memory leaks, the leaks program will tell you how many, and give stack traces for each. You can file a report, along with a description of what steps you took to get the leak, at Bugzilla. Put “LEAK:” at the start of the title so that it's easy to find.
If you want to write an even better bug report, see if you can reproduce the leak by following some specific set of steps, and include them in the bug. You can also look at the backtraces in the leak report and see if you can eliminate duplicates. It’s useful to file a separate bug report for each unique leak, and to consolidate duplicate leaks on different sites. Also, check out our general document about filing bugs.
Leaks in Standard Tests
We have two ways to automatically record stack traces for leaks encountered in our standard webkit tests. This is extremely useful since the webkit tests cover many unusual cases that one might not run into during a short browsing session. As we continue to add webkit tests this will continue to test for leaks in more and more corners of the code.
- (Fast) To get a single leaks report covering all webkit tests, use run-webkit-tests --leaks. You can also pass a specific directory or a specific test to get a leaks report covering just part of the test hierarchy. For example run-webkit-tests --leaks dom/html/level1.
- (Slow) To get a separate leaks report for each test, use run-webkit-tests --leaks --singly. Again, you can pass a specific directory to run this on only part of the test hierarchy. This option is much slower, but can be very helpful in pinning down a leak.
Fixing memory leaks is a bit of a black art. The leak checker will tell you where the leaked memory was allocated, but not why it was never freed. Sometimes it will be obvious from code inspection that there is no free call to match a particular allocation. Other times, things get trickier - especially when refcounting is involved. In that case, you know that some code has taken a ref without releasing it, but it can be very hard to tell what code.
Here’s a trick often found useful for these situations. Fire up the application in
breakpoints on the appropriate ref and deref methods. Then, use the gdb “commands” feature to set
commands of “bt 10; cont” for these breakpoints. You’ll get a 10-frame backtrace for every ref and
deref, and that’s often enough to find the one that doesn’t pair up.
Destroy All Leaks
If you want to help with finding and fixing leaks, and you need more advice, contact us. Happy hunting.