1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_DEBUG_LEAK_TRACKER_H_ 6*635a8641SAndroid Build Coastguard Worker #define BASE_DEBUG_LEAK_TRACKER_H_ 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker #include <stddef.h> 9*635a8641SAndroid Build Coastguard Worker 10*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h" 11*635a8641SAndroid Build Coastguard Worker 12*635a8641SAndroid Build Coastguard Worker // Only enable leak tracking in non-uClibc debug builds. 13*635a8641SAndroid Build Coastguard Worker #if !defined(NDEBUG) && !defined(__UCLIBC__) 14*635a8641SAndroid Build Coastguard Worker #define ENABLE_LEAK_TRACKER 15*635a8641SAndroid Build Coastguard Worker #endif 16*635a8641SAndroid Build Coastguard Worker 17*635a8641SAndroid Build Coastguard Worker #ifdef ENABLE_LEAK_TRACKER 18*635a8641SAndroid Build Coastguard Worker #include "base/containers/linked_list.h" 19*635a8641SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h" 20*635a8641SAndroid Build Coastguard Worker #include "base/logging.h" 21*635a8641SAndroid Build Coastguard Worker #endif // ENABLE_LEAK_TRACKER 22*635a8641SAndroid Build Coastguard Worker 23*635a8641SAndroid Build Coastguard Worker // LeakTracker is a helper to verify that all instances of a class 24*635a8641SAndroid Build Coastguard Worker // have been destroyed. 25*635a8641SAndroid Build Coastguard Worker // 26*635a8641SAndroid Build Coastguard Worker // It is particularly useful for classes that are bound to a single thread -- 27*635a8641SAndroid Build Coastguard Worker // before destroying that thread, one can check that there are no remaining 28*635a8641SAndroid Build Coastguard Worker // instances of that class. 29*635a8641SAndroid Build Coastguard Worker // 30*635a8641SAndroid Build Coastguard Worker // For example, to enable leak tracking for class net::URLRequest, start by 31*635a8641SAndroid Build Coastguard Worker // adding a member variable of type LeakTracker<net::URLRequest>. 32*635a8641SAndroid Build Coastguard Worker // 33*635a8641SAndroid Build Coastguard Worker // class URLRequest { 34*635a8641SAndroid Build Coastguard Worker // ... 35*635a8641SAndroid Build Coastguard Worker // private: 36*635a8641SAndroid Build Coastguard Worker // base::LeakTracker<URLRequest> leak_tracker_; 37*635a8641SAndroid Build Coastguard Worker // }; 38*635a8641SAndroid Build Coastguard Worker // 39*635a8641SAndroid Build Coastguard Worker // 40*635a8641SAndroid Build Coastguard Worker // Next, when we believe all instances of net::URLRequest have been deleted: 41*635a8641SAndroid Build Coastguard Worker // 42*635a8641SAndroid Build Coastguard Worker // LeakTracker<net::URLRequest>::CheckForLeaks(); 43*635a8641SAndroid Build Coastguard Worker // 44*635a8641SAndroid Build Coastguard Worker // Should the check fail (because there are live instances of net::URLRequest), 45*635a8641SAndroid Build Coastguard Worker // then the allocation callstack for each leaked instances is dumped to 46*635a8641SAndroid Build Coastguard Worker // the error log. 47*635a8641SAndroid Build Coastguard Worker // 48*635a8641SAndroid Build Coastguard Worker // If ENABLE_LEAK_TRACKER is not defined, then the check has no effect. 49*635a8641SAndroid Build Coastguard Worker 50*635a8641SAndroid Build Coastguard Worker namespace base { 51*635a8641SAndroid Build Coastguard Worker namespace debug { 52*635a8641SAndroid Build Coastguard Worker 53*635a8641SAndroid Build Coastguard Worker #ifndef ENABLE_LEAK_TRACKER 54*635a8641SAndroid Build Coastguard Worker 55*635a8641SAndroid Build Coastguard Worker // If leak tracking is disabled, do nothing. 56*635a8641SAndroid Build Coastguard Worker template<typename T> 57*635a8641SAndroid Build Coastguard Worker class LeakTracker { 58*635a8641SAndroid Build Coastguard Worker public: 59*635a8641SAndroid Build Coastguard Worker // This destructor suppresses warnings about instances of this class not being 60*635a8641SAndroid Build Coastguard Worker // used. ~LeakTracker()61*635a8641SAndroid Build Coastguard Worker ~LeakTracker() {} CheckForLeaks()62*635a8641SAndroid Build Coastguard Worker static void CheckForLeaks() {} NumLiveInstances()63*635a8641SAndroid Build Coastguard Worker static int NumLiveInstances() { return -1; } 64*635a8641SAndroid Build Coastguard Worker }; 65*635a8641SAndroid Build Coastguard Worker 66*635a8641SAndroid Build Coastguard Worker #else 67*635a8641SAndroid Build Coastguard Worker 68*635a8641SAndroid Build Coastguard Worker // If leak tracking is enabled we track where the object was allocated from. 69*635a8641SAndroid Build Coastguard Worker 70*635a8641SAndroid Build Coastguard Worker template<typename T> 71*635a8641SAndroid Build Coastguard Worker class LeakTracker : public LinkNode<LeakTracker<T> > { 72*635a8641SAndroid Build Coastguard Worker public: 73*635a8641SAndroid Build Coastguard Worker LeakTracker() { 74*635a8641SAndroid Build Coastguard Worker instances()->Append(this); 75*635a8641SAndroid Build Coastguard Worker } 76*635a8641SAndroid Build Coastguard Worker 77*635a8641SAndroid Build Coastguard Worker ~LeakTracker() { 78*635a8641SAndroid Build Coastguard Worker this->RemoveFromList(); 79*635a8641SAndroid Build Coastguard Worker } 80*635a8641SAndroid Build Coastguard Worker 81*635a8641SAndroid Build Coastguard Worker static void CheckForLeaks() { 82*635a8641SAndroid Build Coastguard Worker // Walk the allocation list and print each entry it contains. 83*635a8641SAndroid Build Coastguard Worker size_t count = 0; 84*635a8641SAndroid Build Coastguard Worker 85*635a8641SAndroid Build Coastguard Worker // Copy the first 3 leak allocation callstacks onto the stack. 86*635a8641SAndroid Build Coastguard Worker // This way if we hit the CHECK() in a release build, the leak 87*635a8641SAndroid Build Coastguard Worker // information will be available in mini-dump. 88*635a8641SAndroid Build Coastguard Worker const size_t kMaxStackTracesToCopyOntoStack = 3; 89*635a8641SAndroid Build Coastguard Worker StackTrace stacktraces[kMaxStackTracesToCopyOntoStack]; 90*635a8641SAndroid Build Coastguard Worker 91*635a8641SAndroid Build Coastguard Worker for (LinkNode<LeakTracker<T> >* node = instances()->head(); 92*635a8641SAndroid Build Coastguard Worker node != instances()->end(); 93*635a8641SAndroid Build Coastguard Worker node = node->next()) { 94*635a8641SAndroid Build Coastguard Worker StackTrace& allocation_stack = node->value()->allocation_stack_; 95*635a8641SAndroid Build Coastguard Worker 96*635a8641SAndroid Build Coastguard Worker if (count < kMaxStackTracesToCopyOntoStack) 97*635a8641SAndroid Build Coastguard Worker stacktraces[count] = allocation_stack; 98*635a8641SAndroid Build Coastguard Worker 99*635a8641SAndroid Build Coastguard Worker ++count; 100*635a8641SAndroid Build Coastguard Worker if (LOG_IS_ON(ERROR)) { 101*635a8641SAndroid Build Coastguard Worker LOG_STREAM(ERROR) << "Leaked " << node << " which was allocated by:"; 102*635a8641SAndroid Build Coastguard Worker allocation_stack.OutputToStream(&LOG_STREAM(ERROR)); 103*635a8641SAndroid Build Coastguard Worker } 104*635a8641SAndroid Build Coastguard Worker } 105*635a8641SAndroid Build Coastguard Worker 106*635a8641SAndroid Build Coastguard Worker CHECK_EQ(0u, count); 107*635a8641SAndroid Build Coastguard Worker 108*635a8641SAndroid Build Coastguard Worker // Hack to keep |stacktraces| and |count| alive (so compiler 109*635a8641SAndroid Build Coastguard Worker // doesn't optimize it out, and it will appear in mini-dumps). 110*635a8641SAndroid Build Coastguard Worker if (count == 0x1234) { 111*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < kMaxStackTracesToCopyOntoStack; ++i) 112*635a8641SAndroid Build Coastguard Worker stacktraces[i].Print(); 113*635a8641SAndroid Build Coastguard Worker } 114*635a8641SAndroid Build Coastguard Worker } 115*635a8641SAndroid Build Coastguard Worker 116*635a8641SAndroid Build Coastguard Worker static int NumLiveInstances() { 117*635a8641SAndroid Build Coastguard Worker // Walk the allocation list and count how many entries it has. 118*635a8641SAndroid Build Coastguard Worker int count = 0; 119*635a8641SAndroid Build Coastguard Worker for (LinkNode<LeakTracker<T> >* node = instances()->head(); 120*635a8641SAndroid Build Coastguard Worker node != instances()->end(); 121*635a8641SAndroid Build Coastguard Worker node = node->next()) { 122*635a8641SAndroid Build Coastguard Worker ++count; 123*635a8641SAndroid Build Coastguard Worker } 124*635a8641SAndroid Build Coastguard Worker return count; 125*635a8641SAndroid Build Coastguard Worker } 126*635a8641SAndroid Build Coastguard Worker 127*635a8641SAndroid Build Coastguard Worker private: 128*635a8641SAndroid Build Coastguard Worker // Each specialization of LeakTracker gets its own static storage. 129*635a8641SAndroid Build Coastguard Worker static LinkedList<LeakTracker<T> >* instances() { 130*635a8641SAndroid Build Coastguard Worker static LinkedList<LeakTracker<T> > list; 131*635a8641SAndroid Build Coastguard Worker return &list; 132*635a8641SAndroid Build Coastguard Worker } 133*635a8641SAndroid Build Coastguard Worker 134*635a8641SAndroid Build Coastguard Worker StackTrace allocation_stack_; 135*635a8641SAndroid Build Coastguard Worker }; 136*635a8641SAndroid Build Coastguard Worker 137*635a8641SAndroid Build Coastguard Worker #endif // ENABLE_LEAK_TRACKER 138*635a8641SAndroid Build Coastguard Worker 139*635a8641SAndroid Build Coastguard Worker } // namespace debug 140*635a8641SAndroid Build Coastguard Worker } // namespace base 141*635a8641SAndroid Build Coastguard Worker 142*635a8641SAndroid Build Coastguard Worker #endif // BASE_DEBUG_LEAK_TRACKER_H_ 143