We’re Hunting Memory Leaks

We’ve heard a number of reports of Safari memory leaks, and we’d like to fix a bunch of these. This is a very important factor for usability of Safari and other WebKit apps. You can help! Here’s how:

Finding Leaks

The Mac OS X Developer Tools include a very useful program for leak detection. Here’s how you can use it:

  1. Get a fresh WebKit build, ideally a Development build as this turns off the various custom allocators in WebKit.
  2. Set the MallocStackLogging environment variable to YES (in bash, export MallocStackLogging=YES, in tcsh, setenv MallocStackLogging YES).
  3. Run Safari using run-safari
  4. Browse around a little
  5. From the command line, run leaks Safari

At this point, if you found memory leaks, the leaks program will tell you how many, and give stack traces for each. You can file this report, along with a description of what steps you took to get the leak, in bugzilla. Put “LEAK:” at the start of the title so these bugs are easy to find.

If you want to make an even better bug report, see if you can reproduce the leak by following some specific set of steps, and include that in the bug. You can also look at the backtraces in the leak report and see if you can match up ones that look the same. It’s useful to file a separate bug report for each one that looks different, and to consolidate leaks on different sites that look like they have the same stack trace.

Fixing Leaks

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 often know that some code is holding an extra ref without releasing it, but it can be very hard to tell what code.

Here’s a trick I have often found useful for these situations. Fire up the app in gdb. Set 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, stop by #webkit on freenode. Happy hunting.