1 // Copyright (c) 2012 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_DEBUG_LEAK_TRACKER_H_
6 #define BASE_DEBUG_LEAK_TRACKER_H_
8 #include "build/build_config.h"
10 // Only enable leak tracking in non-uClibc debug builds.
11 #if !defined(NDEBUG) && !defined(__UCLIBC__)
12 #define ENABLE_LEAK_TRACKER
15 #ifdef ENABLE_LEAK_TRACKER
16 #include "base/containers/linked_list.h"
17 #include "base/debug/stack_trace.h"
18 #include "base/logging.h"
19 #endif // ENABLE_LEAK_TRACKER
21 // LeakTracker is a helper to verify that all instances of a class
22 // have been destroyed.
24 // It is particularly useful for classes that are bound to a single thread --
25 // before destroying that thread, one can check that there are no remaining
26 // instances of that class.
28 // For example, to enable leak tracking for class net::URLRequest, start by
29 // adding a member variable of type LeakTracker<net::URLRequest>.
34 // base::LeakTracker<URLRequest> leak_tracker_;
38 // Next, when we believe all instances of net::URLRequest have been deleted:
40 // LeakTracker<net::URLRequest>::CheckForLeaks();
42 // Should the check fail (because there are live instances of net::URLRequest),
43 // then the allocation callstack for each leaked instances is dumped to
46 // If ENABLE_LEAK_TRACKER is not defined, then the check has no effect.
51 #ifndef ENABLE_LEAK_TRACKER
53 // If leak tracking is disabled, do nothing.
58 static void CheckForLeaks() {}
59 static int NumLiveInstances() { return -1; }
64 // If leak tracking is enabled we track where the object was allocated from.
67 class LeakTracker
: public LinkNode
<LeakTracker
<T
> > {
70 instances()->Append(this);
74 this->RemoveFromList();
77 static void CheckForLeaks() {
78 // Walk the allocation list and print each entry it contains.
81 // Copy the first 3 leak allocation callstacks onto the stack.
82 // This way if we hit the CHECK() in a release build, the leak
83 // information will be available in mini-dump.
84 const size_t kMaxStackTracesToCopyOntoStack
= 3;
85 StackTrace stacktraces
[kMaxStackTracesToCopyOntoStack
];
87 for (LinkNode
<LeakTracker
<T
> >* node
= instances()->head();
88 node
!= instances()->end();
89 node
= node
->next()) {
90 StackTrace
& allocation_stack
= node
->value()->allocation_stack_
;
92 if (count
< kMaxStackTracesToCopyOntoStack
)
93 stacktraces
[count
] = allocation_stack
;
96 if (LOG_IS_ON(ERROR
)) {
97 LOG_STREAM(ERROR
) << "Leaked " << node
<< " which was allocated by:";
98 allocation_stack
.OutputToStream(&LOG_STREAM(ERROR
));
104 // Hack to keep |stacktraces| and |count| alive (so compiler
105 // doesn't optimize it out, and it will appear in mini-dumps).
106 if (count
== 0x1234) {
107 for (size_t i
= 0; i
< kMaxStackTracesToCopyOntoStack
; ++i
)
108 stacktraces
[i
].Print();
112 static int NumLiveInstances() {
113 // Walk the allocation list and count how many entries it has.
115 for (LinkNode
<LeakTracker
<T
> >* node
= instances()->head();
116 node
!= instances()->end();
117 node
= node
->next()) {
124 // Each specialization of LeakTracker gets its own static storage.
125 static LinkedList
<LeakTracker
<T
> >* instances() {
126 static LinkedList
<LeakTracker
<T
> > list
;
130 StackTrace allocation_stack_
;
133 #endif // ENABLE_LEAK_TRACKER
138 #endif // BASE_DEBUG_LEAK_TRACKER_H_