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 bugreports 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:
export MallocStackLogging=YES
,
in tcsh, setenv MallocStackLogging YES
).
run-safari
.
leaks Safari
.
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.
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.
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 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.
If you want to help with finding and fixing leaks, and you need more advice, contact us. Happy hunting.