Memory Leaks

Common types of memory leaks

Most objects inside Mozilla-based apps support XPCOM and use reference counting. This works quite well, and in most cases you’ll never have to worry about leaking memory as long as you use nsCOMPtr and related templates to manage your pointers. However, it’s still possible to leak. The most common types of links that I’ve come across:

  • Reference cycles. This is the biggest if you reference one XPCOM object from another and have a reference back, then neither object will ever be freed. This can get much more complex if a chain of objects is involved, each of which references another (with the last referencing the first one).
  • XPConnect. JavaScript uses garbage collection, so you generally don’t have to worry about JS objects leaking. But when you use XPConnect to use XPCOM objects in JS, it’s quite easy to end up with leaks.
  • Reference miscounting. If you need to call NS_ADDREF explicitly (return a newly created object, for example) and you do so incorrectly, a leak will occur.
  • Third-party libraries. Obviously if you are using third-party library that doesn’t have reference counting, you need to be careful to free any memory that the library allocates if it doesn’t do so itself.

Finding memory leaks

General approach

The first rule of finding memory leaks is to not create them in the first place. An awareness of the above-mentioned issues is invaluable in order to keep the amount of time we spend on this to a minimum. The next step I follow is to start with the absolute minimal use case (starting app and quitting). If there are leaks, those should be fixed first. I’m personally in favor of having a zero leak policy so we can immediately see if something is wrong, but if that’s not feasible (leaks due to Mozilla or some third-party library that can’t be fixed), we should keep them to an absolute minimum and document any that simply can’t be fixed.

Once all the leaks are fixed for the simplest case, then test a slightly more complex case (e.g. open and close navigator) and fix any resulting leaks. By proceeding in this way, you keep the number of leaks to a minimum for each cycle, which makes it much easier to figure out what’s going on.

Specific techniques

A good article about finding leaks in Mozilla is David Baron’s Finding leaks in Mozilla.

Normal leaks

For finding out whether stuff is leaking and what is leaking, Purify can be very useful. I’ve had success with both debug and release builds of Mozilla. Make sure that you run the app first so that all components are registered. Then start it in Purify. If you have problems like strange error messages appearing, it might help to delete all the files from the Purify cache and trying again. Once you quite Firefox, you’ll see a node in the list of Purify messages that lists all the objects that leaked. Supposedly only real memory leaks (not potential leaks) are interesting. Also, I’m not 100% convinced that Purify catches all leaks.

Refcounted objects

If your leaks a result of a non-reference counted object or other block of memory, Purify may be all you ever needs to find and fix them. For XPCOM objects, however, it can only tell you that something is leaking and where it was initially allocated. This isn’t that much help since you can’t tell who has addref’ed and released it since then.

In these cases I use my apRefCountLogger class. First of all, make sure that you have the latest patch from bug 322959 applied (and rebuild XPCOM). It only works in debug mode. Then put the following line in the C++ file on the class you want to analyze, directly about the

NS_IMPL_ISUPPORTS

macro:

#include "apRefCountLogger.h"

That’s it. A “leaks.txt” file will appear in your Firefox bin directory on shutdown. If the file is empty, then you have no leaks.

Note that the stackwalking code may interfere with Purify, so remove any references to apRefCountLogger.h from your sources before running Purify.

JavaScript/XPConnect

The most common cause of leaks when using JavaScript and XPConnect is registering a JavaScript listener or observer with a C++ component and forgetting to remove it. This will cause the JavaScript component (anything that it references) to remain in memory. Make absolutely sure that all JavaScript objects registered with C++ components are removed when appropriate (at the latest when the relevant window is closed). Using XPCOM in JavaScript without leaking provides a more complete description of cases where JS/XPCOM leaks may occur.

To find JS/XPCOM leaks, you can use David Baron’s Leak Monitor Extension. This will popup a window when leaks occur and dump remaining leaks to the console on shutdown. If this doesn’t help and you still have leaks, the link at the beginning of this section offers some tips about how to modify the JavaScript and XPConnect sources in order to get detailed logs of all XPConnect activity and leaks.

 
src/hack/memory_leaks.txt · Last modified: 2007/03/06 14:14 by jakub
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki