зеркало из https://github.com/mozilla/gecko-dev.git
529 строки
31 KiB
HTML
529 строки
31 KiB
HTML
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<meta name="GENERATOR" content="Mozilla/4.51 [en] (WinNT; U) [Netscape]">
|
|
</head>
|
|
<body>
|
|
|
|
<center>
|
|
<h1>
|
|
How to debug memory leaks/refcnt leaks</h1></center>
|
|
|
|
<center>Last update: October 21st, 1999</center>
|
|
|
|
<h2>
|
|
What tools do we have?</h2>
|
|
The mozilla team has developed a number of memory analysis tools to augment
|
|
commercial tools like Purify. These can help us more quickly spot and fix
|
|
memory leaks and memory bloat (our term for taking up too much memory,
|
|
aka footprint). Here's a list of what we have at our disposal:
|
|
<ul>
|
|
<li>
|
|
<b>BloatView </b>- This tool dumps out per-class statistics on the total
|
|
number of refcounts and instances, as well as unreleased refcounts and
|
|
un-deleted instances, and the amount of memory consumed by them. (more
|
|
<a href="#BloatView">below</a>)</li>
|
|
|
|
<li>
|
|
<b>Boehm GC Leak Detector </b>- The Boehm garbage collector has be modified
|
|
to serve as a leak detector. It's output can be post-processed by the "Leak
|
|
Soup" tool to find the roots of leaked objects. This lets developers quickly
|
|
focus on the key objects that need to be freed, rather than the whole graph
|
|
of objects to which they refer. (more <a href="#Boehm">below</a>)</li>
|
|
|
|
<li>
|
|
<b>Refcount Tracing</b> - Stack traces can also be dumped out for object
|
|
allocations and refcounting. This information can be post-processed by
|
|
the <a href="http://www.mozilla.org/performance/refcnt-balancer.html">Refcount
|
|
Balancer</a> tool to match up AddRefs and Releases to find the code that
|
|
has missing Releases. (more <a href="#RefcountTracing">below</a>)</li>
|
|
|
|
<li>
|
|
<b>Leaky</b> - This tool also dumps out stack traces (in a slightly different
|
|
format) and can again be used to match up AddRefs with Releases in order
|
|
to find missing Release calls. (more <a href="#Leaky">below</a>)</li>
|
|
|
|
<li>
|
|
<b>Menu items to interactively control Purify</b> - Interactively triggering
|
|
a dump of all leaks or new leaks from within the running application is
|
|
still one of the best ways to debug leaks in your subsystem. Menu items
|
|
for this can be enabled for both viewer and apprunner. (more <a href="#Purify">below</a>)</li>
|
|
</ul>
|
|
More description on each of these will be provided below.
|
|
<h2>
|
|
How to turn on refcnt/memory logging</h2>
|
|
Assuming you have a build with refcnt logging enabled (we'll tell you how
|
|
to do that next), here's what you have to do to use it. All of the following
|
|
environment variables can be set to any of these values:
|
|
<ul>
|
|
<li>
|
|
<b>1</b> - log to stdout</li>
|
|
|
|
<li>
|
|
<b>2</b> - log to stderr</li>
|
|
|
|
<li>
|
|
<b><i>filename</i></b> - write log to a file</li>
|
|
</ul>
|
|
The log environment variables are:
|
|
<blockquote>XPCOM_MEM_BLOAT_LOG</blockquote>
|
|
|
|
<blockquote>
|
|
<blockquote>If this environment variable is set then xpcom will use the
|
|
"bloat" trackers. The bloat trackers gather data for the BloatView output
|
|
that occurs when the program exits, when about:bloat is loaded, or a call
|
|
to nsTraceRefcnt::DumpStatistics is made.
|
|
<p>When an addref/release/ctor/dtor call is made, the data is logged and
|
|
attributed to the particular data type.
|
|
<p>By default enabling this environment variable will cause the BloatView
|
|
software to dump out the entire database of collected data. If all you
|
|
want to see is that data for objects that leaked, set the environment variable
|
|
XPCOM_MEM_LEAK_LOG.</blockquote>
|
|
XPCOM_MEM_LEAK_LOG
|
|
<blockquote>This is basically a subset of XPCOM_MEM_BLOAT_LOG, and only
|
|
shows classes that had object that were leaked, instead of statistics for
|
|
all classes.</blockquote>
|
|
XPCOM_MEM_REFCNT_LOG
|
|
<blockquote>Setting this environment variable enables refcount tracing.
|
|
<br>Only enable this for severe pain (unless you are using refcount tracing
|
|
or leaky, see below). What this does is to enable logging (to stdout) of
|
|
each and every call to addref/release without discrimination to the types
|
|
involved. The output includes mapping the call-stacks at the time of the
|
|
call to symbolic forms (on platforms that support this) and thus will be
|
|
*very* *VERY* *VERY* slow. Did I say slow?</blockquote>
|
|
XPCOM_MEM_ALLOC_LOG
|
|
<blockquote>For losing architectures (those that don't have stack-crawl
|
|
software written for them), xpcom supports logging at the *call site* to
|
|
AddRef/Release using the usual cpp __FILE__ and __LINE__ number macro expansion
|
|
hackery. This results in slower code, but at least you get *some* data
|
|
about where the leaks might be occurring from.</blockquote>
|
|
XPCOM_MEM_LEAKY_LOG
|
|
<blockquote>For platforms that support leaky, xpcom will endeavor to find
|
|
at run time the symbols "__log_addref" and "__log_release" and if found,
|
|
instead of doing the slow painful stack crawls at program execution time
|
|
instead it will pass the buck to the leaky software. This will allow your
|
|
program to actually run in user friendly real time, but does require that
|
|
your platform support leaky. Currently only linux supports leaky.</blockquote>
|
|
</blockquote>
|
|
In addition, the following variable may be set to a list of class names:
|
|
<blockquote>XPCOM_MEM_LOG_CLASSES</blockquote>
|
|
|
|
<blockquote>
|
|
<blockquote>Instead of slowing to a useless, instead you can slow to a
|
|
meer crawl by using this option. When enabled, the xpcom logging software
|
|
will look for the XPCOM_MEM_LOG_CLASSES environment variable (for platforms
|
|
that support getenv). The variable contains a comma seperated list of names
|
|
which will be used to compare against the type's of the objects being logged.
|
|
For example:
|
|
<blockquote>env XPCOM_MEM_LOG_CLASSES=nsWebShell XPCOM_MEM_REFCNT_LOG=1
|
|
./apprunner</blockquote>
|
|
|
|
will show you just the AddRef/Release calls to instances of nsWebShell
|
|
while running apprunner.Note that setting XPCOM_MEM_LOG_CLASSES will
|
|
also list the <i>serial number</i> of each object that leaked in the
|
|
"bloat log" (that is, the file specified by the XPCOM_MEM_BLOAT_LOG
|
|
variable). An object's serial number is simply a unique number,
|
|
starting at one, that is assigned to the object when it is allocated.
|
|
</blockquote>
|
|
</blockquote>
|
|
|
|
You may use an object's serial number with the following variable to
|
|
further restrict the reference count tracing:
|
|
|
|
<blockquote>XPCOM_MEM_LOG_OBJECTS</blockquote>
|
|
|
|
<blockquote>
|
|
<blockquote>Set this variable to a comma-separated list of object
|
|
<i>serial number</i>. When this is set, along with
|
|
XPCOM_MEM_LOG_CLASSES and XPCOM_MEM_REFCNT_LOG, a stack track will be
|
|
generated for <em>only</em> the specific objects that you list. For
|
|
example,
|
|
|
|
<blockquote>env XPCOM_MEM_LOG_CLASSES=nsWebShell XPCOM_MEM_LOG_OBJECTS=2 XPCOM_MEM_REFCNT_LOG=1
|
|
./apprunner</blockquote>
|
|
|
|
will dump stack traces to the console for the 2nd
|
|
<code>nsWebShell</code> object that gets allocated, and nothing else.
|
|
</blockquote>
|
|
</blockquote>
|
|
|
|
<hr WIDTH="100%">
|
|
<h2>
|
|
<a NAME="BloatView"></a>1. BloatView</h2>
|
|
BloatView dumps out per-class statistics on allocations and refcounts,
|
|
and provides gross numbers on the amount of memory being leaked broken
|
|
down by class. Here's a sample of the BloatView output:
|
|
<pre>== BloatView: ALL (cumulative) LEAK AND BLOAT STATISTICS
|
|
|
|
|<------Class----->|<-----Bytes------>|<----------------Objects---------------->|<--------------References-------------->|
|
|
Per-Inst Leaked Total Rem Mean StdDev Total Rem Mean StdDev
|
|
0 TOTAL 193 2480436 316271 12852 ( 5377.07 +/- 5376.38) 410590 16079 ( 2850.93 +/- 2849.79)
|
|
1 StyleSetImpl 32 0 8 0 ( 3.88 +/- 3.15) 6304 0 ( 7.18 +/- 6.63)
|
|
2 SinkContext 32 0 19 0 ( 1.87 +/- 1.04) 0 0 ( 0.00 +/- 0.00)
|
|
3 nsXPCClasses 12 0 2 0 ( 1.00 +/- 0.71) 41 0 ( 5.57 +/- 4.98)
|
|
4 NameSpaceURIKey 8 72 158 9 ( 8.16 +/- 7.62) 0 0 ( 0.00 +/- 0.00)
|
|
5 nsSupportsArray 36 11304 2581 314 ( 477.13 +/- 476.53) 9223 314 ( 579.23 +/- 578.64)
|
|
6 nsView 96 0 57 0 ( 27.64 +/- 26.98) 0 0 ( 0.00 +/- 0.00)
|
|
7 nsEnderDocumentObser 12 0 1 0 ( 0.50 +/- 0.87) 1 0 ( 0.50 +/- 0.87)</pre>
|
|
Here's how you interpret the columns:
|
|
<ul>
|
|
<li>
|
|
<b>Class</b> - The name of the class in question. (Warning: The class name
|
|
is truncated to 20 characters.)</li>
|
|
|
|
<li>
|
|
<b>Bytes Per-Inst </b>- The number of bytes returned if you were to write
|
|
sizeof(<i>Class</i>). Note that this number does not reflect any memory
|
|
held onto by the class, such as internal buffers, etc. (E.g. for nsStr
|
|
-- you're seeing the size of the header struct, not the size of the string!)</li>
|
|
|
|
<li>
|
|
<b>Bytes Leaked</b> - The number of bytes per instance times the number
|
|
of objects leaked (Bytes Per-Inst * Objects Rem). Use this number to look
|
|
for the worst offenders. <font color="#FF0000">(Should be zero!)</font></li>
|
|
|
|
<li>
|
|
<b>Objects Total</b> - The total count of objects allocated of a given
|
|
class.</li>
|
|
|
|
<li>
|
|
<b>Objects Rem</b> - The number of objects allocated of a given class that
|
|
weren't deleted. <font color="#FF0000">(Should be zero!)</font></li>
|
|
|
|
<li>
|
|
<b>Objects Mean</b> - The mean (average) number of objects of a given class
|
|
across the lifetime of the run. Data points are taken whenever new and
|
|
delete are called (not at regular intervals).</li>
|
|
|
|
<li>
|
|
<b>Objects StdDev</b> - The standard deviation in the mean number of objects
|
|
allocated.</li>
|
|
|
|
<li>
|
|
<b>References Total </b>- The total number of AddRefs performed on a given
|
|
class.</li>
|
|
|
|
<li>
|
|
<b>References Rem</b> - The number of references on a given class that
|
|
weren't Released. <font color="#FF0000">(Should be zero!)</font></li>
|
|
|
|
<li>
|
|
<b>References Mean</b> - The mean (average) number of references to a given
|
|
class across the lifetime of the run. Data points are taken whenever AddRef
|
|
and Release are called (not at regular intervals).</li>
|
|
|
|
<li>
|
|
<b>References StdDev</b> - The standard deviation in the mean number of
|
|
references</li>
|
|
</ul>
|
|
Interesting things to look for:
|
|
<ul>
|
|
<li>
|
|
<b><font color="#FF0000">Are your classes in the list?</font></b> - Look!
|
|
If they aren't, then you're not using the NS_IMPL_ADDREF and NS_IMPL_RELEASE
|
|
(or NS_IMPL_ISUPPORTS which calls them) for xpcom objects, or MOZ_COUNT_CTOR
|
|
and MOZ_COUNT_DTOR for non-xpcom objects. Not having your classes in the
|
|
list is <i>not</i> ok. That means no one is looking at them, and we won't
|
|
be able to tell if someone introduces a leak. (see <a href="#Instrumenting">below</a>
|
|
for how to fix this)</li>
|
|
|
|
<li>
|
|
<b><font color="#FF0000">The Bytes Leaked for your classes should be zero!</font></b>
|
|
- Need I say more? If it isn't, you should use the other tools to fix it.</li>
|
|
|
|
<li>
|
|
<b>The number of objects remaining might be equal to the total number of
|
|
objects.</b> This could indicate a hand-written Release method (that doesn't
|
|
use the NS_LOG_RELEASE macro from nsTraceRefcnt.h), or perhaps you're just
|
|
not freeing any of the instances you've allocated. These sorts of leaks
|
|
are easy to fix.</li>
|
|
|
|
<li>
|
|
<b>The total number of objects might be 1.</b> This might indicate a global
|
|
variable or service. Usually this will have a large number of refcounts.</li>
|
|
|
|
<li>
|
|
<b>The number of refcounts might equal the total number of objects.</b>
|
|
This class might be a candidate for a non-xpcom object (but be very cautious
|
|
about changing this if it implements any interfaces besides nsISupports).</li>
|
|
|
|
<li>
|
|
<b>The mean number of objects is much lower than the total.</b> This indicates
|
|
a few objects of this class are allocated and then freed, as opposed to
|
|
the opposite case where there's a big build-up of instances that are all
|
|
freed together (perhaps at the end of the program).</li>
|
|
</ul>
|
|
You can also dump out bloat statistics interactively by typing <a href="about:bloat">about:bloat</a>
|
|
in the location bar, or by using the menu items under the QA menu in debug
|
|
builds. Note that you need to have the XPCOM_MEM_BLOAT_LOG or XPCOM_MEM_LEAK_LOG
|
|
envirionment variable defined first. You can also type <a href="about:bloat?new">about:bloat?new</a>
|
|
to get a log since the last time you called it, or <a href="about:bloat?clear">about:bloat?clear</a>
|
|
to clear the current set of statistics completely (use this option with
|
|
caution as it can result in what look like negative refcounts, etc). Whenever
|
|
these options are used, the log data is dumped to a file relative to the
|
|
program's directory:
|
|
<blockquote>bloatlogs/all-1999-10-16-010302.txt
|
|
(a complete log resulting from the about:bloat command)
|
|
<br>bloatlogs/new-1999-10-16-010423.txt (an incremental
|
|
log resulting from the about:bloat?new command)</blockquote>
|
|
|
|
<h3>
|
|
Comparing Bloat Logs</h3>
|
|
You can also compare any two bloat logs (either those produced when the
|
|
program shuts down, or written to the bloatlogs directory) by running the
|
|
following program:
|
|
<blockquote>perl mozilla/tools/tinderbox/bloatdiff.pl <previous-log>
|
|
<current-log></blockquote>
|
|
This will give you output of the form:
|
|
<blockquote>
|
|
<pre>Bloat/Leak Delta Report
|
|
Current file: dist/win32_D.OBJ/bin/bloatlogs/all-1999-10-22-133450.txt
|
|
Previous file: dist/win32_D.OBJ/bin/bloatlogs/all-1999-10-16-010302.txt
|
|
--------------------------------------------------------------------------
|
|
CLASS LEAKS delta BLOAT delta
|
|
--------------------------------------------------------------------------
|
|
TOTAL 6113530 2.79% 67064808 9.18%
|
|
StyleContextImpl 265440 81.19% 283584 -26.99%
|
|
CToken 236500 17.32% 306676 20.64%
|
|
nsStr 217760 14.94% 5817060 7.63%
|
|
nsXULAttribute 113048 -70.92% 113568 -71.16%
|
|
LiteralImpl 53280 26.62% 75840 19.40%
|
|
nsXULElement 51648 0.00% 51648 0.00%
|
|
nsProfile 51224 0.00% 51224 0.00%
|
|
nsFrame 47568 -26.15% 48096 -50.49%
|
|
CSSDeclarationImpl 42984 0.67% 43488 0.67%</pre>
|
|
</blockquote>
|
|
This "delta report" shows the leak offenders, sorted from most leaks to
|
|
fewest. The delta numbers show the percentage change between runs for the
|
|
amount of leaks and amount of bloat (<font color="#FF0000">negative numbers
|
|
are better!</font>). The bloat number is a metric determined by multiplying
|
|
the total number of objects allocated of a given class by the class size.
|
|
Note that although this isn't necessarily the amount of memory consumed
|
|
at any given time, it does give an indication of how much memory we're
|
|
consuming. The more memory in general, the worse the performance and footprint.
|
|
The percentage 99999.99% will show up indicating an "infinite" amount of
|
|
leakage. This happens when something that didn't leak before is now leaking.
|
|
<h3>
|
|
Bloat Statistics on Tinderbox</h3>
|
|
Each build rectangle on Tinderbox will soon be capable of displaying the
|
|
total leaks delta and bloat delta percentages from one build to the next.
|
|
Horray!
|
|
<br>
|
|
<br>
|
|
<center><table BORDER COLS=2 WIDTH="100" HEIGHT="100" >
|
|
<tr>
|
|
<td> <u><font color="#3366FF">warren</font></u></td>
|
|
|
|
<td BGCOLOR="#00CC00"> <u><font color="#3333FF">L</font></u>
|
|
<u><font color="#3333FF">C</font></u>
|
|
<br> L:-3
|
|
<br> B:+21 </td>
|
|
</tr>
|
|
</table></center>
|
|
|
|
<p>Hmmm. Warren checked in and the number of leaks went down by 3%. (Yes!)
|
|
But the amount of bloat went up by 21%. (Ouch!) This probably should be
|
|
investigated further. Sometimes bloat can go up because new features were
|
|
added that just take up more memory (or if the set of test URLs were changed,
|
|
and the activity is different from last time), but in general we'd like
|
|
to see both of these numbers continue to go down. You can look at the end
|
|
of the log (by clicking on the L) to see the bloat statistics and delta
|
|
report for a breakdown of what actually happened.
|
|
<br>
|
|
<hr WIDTH="100%">
|
|
<h2>
|
|
<a NAME="Boehm"></a>2. Boehm GC Leak Detector</h2>
|
|
more...
|
|
<br>
|
|
<hr WIDTH="100%">
|
|
<h2>
|
|
<a NAME="RefcountTracing"></a>3. Refcount Tracing</h2>
|
|
Refcount tracing is used to capture stack traces of AddRef and Release
|
|
calls to use with the Refcount Balancer. It is best to set the XPCOM_MEM_REFCNT_LOG
|
|
environment variable to point to a file when using it.
|
|
<p>See <a href="http://www.mozilla.org/performance/refcnt-balancer.html">Refcount
|
|
Balancer</a> for more information.
|
|
<p>
|
|
<hr WIDTH="100%">
|
|
<h2>
|
|
<a NAME="Leaky"></a>4. Leaky</h2>
|
|
|
|
<h3>
|
|
Using this stuff with leaky</h3>
|
|
First, setup these environment variables:
|
|
<blockquote>setenv LD_PRELOAD ../lib/libleaky.so (assumes you execute apprunner/viewer
|
|
in the dist/bin directory)
|
|
<br>setenv LIBMALLOC_LOG 8 (tells leaky to log addref/release calls)
|
|
<br>setenv XPCOM_MEM_LEAKY_LOG 1 (use leaky)
|
|
<br>setenv XPCOM_MEM_LOG_CLASSES "a,b,c" (the list of types you care about)</blockquote>
|
|
Then run the viewer or the apprunner and run your test. Then exit it. The
|
|
result will be some large file in your current directory called "malloc-log"
|
|
and a small file called "malloc-map". If these aren't there then somethings
|
|
wrong.
|
|
<p>If it works properly, then you now have the tracing data for the problem
|
|
you are chasing in malloc-log. Use leaky to convert it to human readable
|
|
form and debug away:
|
|
<blockquote>leaky -dRq <viewer|apprunner> malloc-log > /tmp/log</blockquote>
|
|
Leaky used to require c++filt, but now it does it itself. With the -R option,
|
|
leaky will only log the refcnts that actually leaked (those that didn't
|
|
go to zero).
|
|
<h3>
|
|
Leaky environment variables</h3>
|
|
|
|
<blockquote>LD_PRELOAD
|
|
<blockquote>Set this to the pathname to libleaky.so if you are using leaky
|
|
to track memory operations.</blockquote>
|
|
LIBMALLOC_LOG
|
|
<blockquote>Set this to "8" to enable leaky to track addref/release calls
|
|
that are logged by xpcom. Note that you must set bit 8 in xpcomrefcnt to
|
|
connect xpcom's tracing to leakys tracing.</blockquote>
|
|
</blockquote>
|
|
|
|
<h3>
|
|
Sample output</h3>
|
|
Here is what you see when you enable some logging with XPCOM_MEM_LOG_CLASSES
|
|
set to something:
|
|
<p>nsWebShell 0x81189f8
|
|
Release 5 nsWebShell::Release(void)+0x59
|
|
nsCOMPtr<nsIContentViewerContainer>::~nsCOMPtr(void)+0x34
|
|
nsChannelListener::OnStartRequest(nsIChannel *, nsISupports *)+0x550
|
|
nsFileChannel::OnStartRequest(nsIChannel *, nsISupports *)+0x7b nsOnStartRequestEvent::HandleEvent(void)+0x46
|
|
nsStreamListenerEvent::HandlePLEvent(PLEvent *)+0x62
|
|
PL_HandleEvent+0x57 PL_ProcessPendingEvents+0x90
|
|
nsEventQueueImpl::ProcessPendingEvents(void)+0x1d nsAppShell::SetDispatchListener(nsDispatchListener
|
|
*)+0x3e gdk_get_show_events+0xbb
|
|
g_io_add_watch+0xaa g_get_current_time+0x136
|
|
g_get_current_time+0x6f1 g_main_run+0x81
|
|
gtk_main+0xb9 nsAppShell::Run(void)+0x245
|
|
nsAppShell::Run(void)+0xc7a92ede nsAppShell::Run(void)+0xc7a9317c
|
|
__libc_start_main+0xeb
|
|
<p>Here is what you see when you use the leaky tool to dump out addref/release
|
|
leaks:
|
|
<p>addref 082cccc8 0 00000001
|
|
--> CViewSourceHTML::AddRef(void) CViewSourceHTML::QueryInterface(nsID
|
|
&, void **) NS_NewViewSourceHTML(nsIDTD **) .LM708 GetSharedObjects(void)
|
|
nsParser::RegisterDTD(nsIDTD *) RDFXMLDataSourceImpl::Refresh(int) nsChromeRegistry::InitRegistry(void)
|
|
nsChromeProtocolHandler::NewChannel(char *, nsIURI *, nsILoadGroup *, nsIEventSinkGetter
|
|
*, nsIChannel **) nsIOService::NewChannelFromURI(char *, nsIURI *, nsILoadGroup
|
|
*, nsIEventSinkGetter *, nsIChannel **) NS_OpenURI(nsIChannel **, nsIURI
|
|
*, nsILoadGroup *, nsIEventSinkGetter *) NS_OpenURI(nsIInputStream **,
|
|
nsIURI *) CSSLoaderImpl::LoadSheet(URLKey &, SheetLoadData *) CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet
|
|
*, nsIURI *, nsString &, int, int) CSSParserImpl::ProcessImport(int
|
|
&, nsString &, nsString &) CSSParserImpl::ParseImportRule(int
|
|
&) CSSParserImpl::ParseAtRule(int &) CSSParserImpl::Parse(nsIUnicharInputStream
|
|
*, nsIURI *, nsICSSStyleSheet *&) CSSLoaderImpl::ParseSheet(nsIUnicharInputStream
|
|
*, SheetLoadData *, int &, nsICSSStyleSheet *&) CSSLoaderImpl::LoadAgentSheet(nsIURI
|
|
*, nsICSSStyleSheet *&, int &, void (*)(nsICSSStyleSheet *, void
|
|
*), void *) nsLayoutModule::Initialize(void) nsLayoutModule::GetClassObject(nsIComponentManager
|
|
*, nsID &, nsID &, void **) nsNativeComponentLoader::GetFactoryFromModule(nsDll
|
|
*, nsID &, nsIFactory **) nsNativeComponentLoader::GetFactory(nsID
|
|
&, char *, char *, nsIFactory **) .LM1381 nsComponentManagerImpl::FindFactory(nsID
|
|
&, nsIFactory **) nsComponentManagerImpl::CreateInstance(nsID &,
|
|
nsISupports *, nsID &, void **) nsComponentManager::CreateInstance(nsID
|
|
&, nsISupports *, nsID &, void **) RDFXMLDataSourceImpl::Refresh(int)
|
|
nsChromeRegistry::InitRegistry(void) nsChromeProtocolHandler::NewChannel(char
|
|
*, nsIURI *, nsILoadGroup *, nsIEventSinkGetter *, nsIChannel **) nsIOService::NewChannelFromURI(char
|
|
*, nsIURI *, nsILoadGroup *, nsIEventSinkGetter *, nsIChannel **) NS_OpenURI(nsIChannel
|
|
**, nsIURI *, nsILoadGroup *, nsIEventSinkGetter *) nsDocumentBindInfo::Bind(nsIURI
|
|
*, nsILoadGroup *, nsIInputStream *, unsigned short *) nsDocLoaderImpl::LoadDocument(nsIURI
|
|
*, char *, nsIContentViewerContainer *, nsIInputStream *, nsISupports *,
|
|
unsigned int, unsigned int, unsigned short *) nsWebShell::DoLoadURL(nsIURI
|
|
*, char *, nsIInputStream *, unsigned int, unsigned int, unsigned short
|
|
*) nsWebShell::LoadURI(nsIURI *, char *, nsIInputStream *, int, unsigned
|
|
int, unsigned int, nsISupports *, unsigned short *) nsWebShell::LoadURL(unsigned
|
|
short *, char *, nsIInputStream *, int, unsigned int, unsigned int, nsISupports
|
|
*, unsigned short *) nsWebShell::LoadURL(unsigned short *, nsIInputStream
|
|
*, int, unsigned int, unsigned int, nsISupports *, unsigned short *) nsWebShellWindow::Initialize(nsIWebShellWindow
|
|
*, nsIAppShell *, nsIURI *, int, int, nsIXULWindowCallbacks *, int, int,
|
|
nsWidgetInitData &) nsAppShellService::JustCreateTopWindow(nsIWebShellWindow
|
|
*, nsIURI *, int, int, unsigned int, nsIXULWindowCallbacks *, int, int,
|
|
nsIWebShellWindow **) nsAppShellService::CreateTopLevelWindow(nsIWebShellWindow
|
|
*, nsIURI *, int, int, unsigned int, nsIXULWindowCallbacks *, int, int,
|
|
nsIWebShellWindow **) OpenChromURL(char *, int, int) HandleBrowserStartup(nsICmdLineService
|
|
*, nsIPref *, int) DoCommandLines(nsICmdLineService *, int) main1(int,
|
|
char **) main __libc_start_main
|
|
<p>
|
|
<hr WIDTH="100%">
|
|
<h2>
|
|
<a NAME="Purify"></a>5. Purify</h2>
|
|
more...
|
|
<br>
|
|
<hr WIDTH="100%">
|
|
<h2>
|
|
How to build xpcom with refcnt/memory logging</h2>
|
|
Built into xpcom is the ability to support the debugging of memory leaks.
|
|
By default, an optimized build of xpcom has this disabled. Also by default,
|
|
the debug builds have the logging facilities enabled. You can control either
|
|
of these options by changing environment variables before you build mozilla:
|
|
<blockquote>FORCE_BUILD_REFCNT_LOGGING</blockquote>
|
|
|
|
<blockquote>
|
|
<blockquote>If this is defined then regardless of the type of build, refcnt
|
|
logging (and related memory debugging) will be enabled in the build.</blockquote>
|
|
NO_BUILD_REFCNT_LOGGING
|
|
<blockquote>If this is defined then regardless of the type of build or
|
|
of the setting of the FORCE_BUILD_REFCNT_LOGGING, no refcnt logging will
|
|
be enabled and no memory debugging will be enabled. This variable overrides
|
|
FORCE_BUILD_REFCNT_LOGGING.</blockquote>
|
|
</blockquote>
|
|
The remaining discussion assumes that one way or another that xpcom has
|
|
been built with refcnt/memory logging enabled.
|
|
<h2>
|
|
<a NAME="Instrumenting"></a>How to instrument your objects for refcnt/memory
|
|
logging</h2>
|
|
First, if your object is an xpcom object and you use the NS_IMPL_ADDREF
|
|
and NS_IMPL_RELEASE (or a variation thereof) macro to implement your AddRef
|
|
and Release methods, then there is nothing you need do. By default, those
|
|
macros support refcnt logging directly.
|
|
<p>If your object is not an xpcom object then some manual editing is in
|
|
order. The following sample code shows what must be done:
|
|
<blockquote><b><tt>MOZ_DECL_CTOR_COUNTER(MyType);</tt></b>
|
|
<p><b><tt>MyType::MyType()</tt></b>
|
|
<br><b><tt>{</tt></b>
|
|
<br><b><tt> MOZ_COUNT_CTOR(MyType);</tt></b>
|
|
<br><b><tt>}</tt></b>
|
|
<p><b><tt>MyType::~MyType()</tt></b>
|
|
<br><b><tt>{</tt></b>
|
|
<br><b><tt> MOZ_COUNT_DTOR(MyType);</tt></b>
|
|
<br><b><tt>}</tt></b></blockquote>
|
|
Now currently the MOZ_DECL_CTOR_COUNTER expands to nothing so your code
|
|
will compile if you forget to add it; however, we reserve the right to
|
|
change that so please put it in.
|
|
<h2>
|
|
What are those macros doing for me anyway?</h2>
|
|
|
|
<p><br><b><tt>NS_IMPL_ADDREF</tt></b> has this additional line in it:
|
|
<blockquote><b><tt>NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this));</tt></b></blockquote>
|
|
What this is doing is logging the addref call using xpcom's nsTraceRefcnt
|
|
class. The implementation of that macro is:
|
|
<br>
|
|
<blockquote><b><tt>#define NS_LOG_ADDREF(_p, _rc, _type, _size) \</tt></b>
|
|
<br><b><tt> nsTraceRefcnt::LogAddRef((_p), (_rc), (_type), (PRUint32)
|
|
(_size))</tt></b></blockquote>
|
|
Which as you can see just passes the buck to nsTraceRefcnt. nsTraceRefcnt
|
|
implements the logging support and will track addref/release/ctor/dtor
|
|
calls in a database that it builds up as the program is executing. In a
|
|
similar manner, NS_IMPL_RELEASE uses NS_LOG_RELEASE which uses nsTraceRefcnt::LogRelease.
|
|
<p>For the MOZ_DECL_CTOR_COUNTER, MOZ_COUNT_CTOR and MOZ_COUNT_DTOR macros
|
|
the expansion boils down to calls to nsTraceRefcnt::LogCtor and nsTraceRefcnt::LogDtor
|
|
calls. Again, the type of the object is passed in as well as the sizeof
|
|
of all the data type.
|
|
<blockquote><b><tt>#define MOZ_COUNT_CTOR(_type)
|
|
\</tt></b>
|
|
<br><b><tt>PR_BEGIN_MACRO
|
|
\</tt></b>
|
|
<br><b><tt> nsTraceRefcnt::LogCtor((void*)this, #_type, sizeof(*this));
|
|
\</tt></b>
|
|
<br><b><tt>PR_END_MACRO</tt></b>
|
|
<p><b><tt>#define MOZ_COUNT_DTOR(_type)
|
|
\</tt></b>
|
|
<br><b><tt>PR_BEGIN_MACRO
|
|
\</tt></b>
|
|
<br><b><tt> nsTraceRefcnt::LogDtor((void*)this, #_type, sizeof(*this));
|
|
\</tt></b>
|
|
<br><b><tt>PR_END_MACRO</tt></b></blockquote>
|
|
|
|
</body>
|
|
</html>
|