// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_LEAK_TRACKER_H_ #define BASE_LEAK_TRACKER_H_ #ifndef NDEBUG #include "base/debug_util.h" #include "base/linked_list.h" #include "base/logging.h" #endif // LeakTracker is a debug helper to verify that all instances of a class // have been destroyed. // // It is particularly useful for classes that are bound to a single thread -- // before destroying that thread, one can check that there are no remaining // instances of that class. // // For example, to enable leak tracking for class URLRequest, start by // adding a member variable of type LeakTracker. // // class URLRequest { // ... // private: // base::LeakTracker leak_tracker_; // }; // // // Next, when we believe all instances of URLRequest have been deleted: // // LeakTracker::CheckForLeaks(); // // Should the check fail (because there are live instances of URLRequest), // then the allocation callstack for each leaked instances is dumped to // the error log. // // In RELEASE mode the check has no effect. namespace base { #ifdef NDEBUG // In release mode we do nothing. template class LeakTracker { public: static void CheckForLeaks() {} static int NumLiveInstances() { return -1; } }; #else // In debug mode we track where the object was allocated from. template class LeakTracker : public LinkNode > { public: LeakTracker() { instances()->Append(this); } ~LeakTracker() { this->RemoveFromList(); } static void CheckForLeaks() { // Walk the allocation list and print each entry it contains. int count = 0; for (LinkNode >* node = instances()->head(); node != instances()->end(); node = node->next()) { ++count; LOG(ERROR) << "Leaked " << node << " which was allocated by:"; node->value()->allocation_stack_.PrintBacktrace(); } DCHECK_EQ(0, count); } static int NumLiveInstances() { // Walk the allocation list and count how many entries it has. int count = 0; for (LinkNode >* node = instances()->head(); node != instances()->end(); node = node->next()) { ++count; } return count; } private: // Each specialization of LeakTracker gets its own static storage. static LinkedList >* instances() { static LinkedList > list; return &list; } StackTrace allocation_stack_; }; #endif // NDEBUG } // namespace base #endif // BASE_LEAK_TRACKER_H_