1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_LEAK_TRACKER_H_
6 #define BASE_LEAK_TRACKER_H_
8 // Only enable leak tracking in debug builds.
10 #define ENABLE_LEAK_TRACKER
13 #ifdef ENABLE_LEAK_TRACKER
14 #include "base/debug_util.h"
15 #include "base/linked_list.h"
16 #include "base/logging.h"
17 #endif // ENABLE_LEAK_TRACKER
19 // LeakTracker is a helper to verify that all instances of a class
20 // have been destroyed.
22 // It is particularly useful for classes that are bound to a single thread --
23 // before destroying that thread, one can check that there are no remaining
24 // instances of that class.
26 // For example, to enable leak tracking for class URLRequest, start by
27 // adding a member variable of type LeakTracker<URLRequest>.
32 // base::LeakTracker<URLRequest> leak_tracker_;
36 // Next, when we believe all instances of URLRequest have been deleted:
38 // LeakTracker<URLRequest>::CheckForLeaks();
40 // Should the check fail (because there are live instances of URLRequest),
41 // then the allocation callstack for each leaked instances is dumped to
44 // If ENABLE_LEAK_TRACKER is not defined, then the check has no effect.
48 #ifndef ENABLE_LEAK_TRACKER
50 // If leak tracking is disabled, do nothing.
54 static void CheckForLeaks() {}
55 static int NumLiveInstances() { return -1; }
60 // If leak tracking is enabled we track where the object was allocated from.
63 class LeakTracker
: public LinkNode
<LeakTracker
<T
> > {
66 instances()->Append(this);
70 this->RemoveFromList();
73 static void CheckForLeaks() {
74 // Walk the allocation list and print each entry it contains.
77 // Copy the first 3 leak allocation callstacks onto the stack.
78 // This way if we hit the CHECK() in a release build, the leak
79 // information will be available in mini-dump.
80 const size_t kMaxStackTracesToCopyOntoStack
= 3;
81 StackTrace stacktraces
[kMaxStackTracesToCopyOntoStack
];
83 for (LinkNode
<LeakTracker
<T
> >* node
= instances()->head();
84 node
!= instances()->end();
85 node
= node
->next()) {
86 StackTrace
& allocation_stack
= node
->value()->allocation_stack_
;
88 if (count
< kMaxStackTracesToCopyOntoStack
)
89 stacktraces
[count
] = allocation_stack
;
92 LOG(ERROR
) << "Leaked " << node
<< " which was allocated by:";
93 allocation_stack
.OutputToStream(&LOG(ERROR
));
98 // Hack to keep |stacktraces| and |count| alive (so compiler
99 // doesn't optimize it out, and it will appear in mini-dumps).
100 if (count
== 0x1234) {
101 for (size_t i
= 0; i
< kMaxStackTracesToCopyOntoStack
; ++i
)
102 stacktraces
[i
].PrintBacktrace();
106 static int NumLiveInstances() {
107 // Walk the allocation list and count how many entries it has.
109 for (LinkNode
<LeakTracker
<T
> >* node
= instances()->head();
110 node
!= instances()->end();
111 node
= node
->next()) {
118 // Each specialization of LeakTracker gets its own static storage.
119 static LinkedList
<LeakTracker
<T
> >* instances() {
120 static LinkedList
<LeakTracker
<T
> > list
;
124 StackTrace allocation_stack_
;
127 #endif // ENABLE_LEAK_TRACKER
131 #endif // BASE_LEAK_TRACKER_H_