OpenShot Library | OpenShotAudio  0.2.1
juce_HeavyweightLeakedObjectDetector.h
1 
2 /** @weakgroup juce_core-memory
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /**
32  This class is a useful way of tracking down hard to find memory leaks when the
33  regular LeakedObjectDetector isn't enough.
34 
35  As well as firing when any instances of the OwnerClass type are leaked, it will
36  print out a stack trace showing where the leaked object was created. This is obviously
37  quite a heavyweight task so, unlike the LeakedObjectDetector which should be always
38  be added to your classes, you should only use this object temporarily when you are
39  debugging and remove it when finished.
40 
41  To use it, use the JUCE_HEAVYWEIGHT_LEAK_DETECTOR macro as a simple way to put
42  one in your class declaration.
43 
44  @tags{Core}
45 */
46 template <class OwnerClass>
48 {
49 public:
50  //==============================================================================
51  HeavyweightLeakedObjectDetector() noexcept { getBacktraceMap()[this] = SystemStats::getStackBacktrace(); }
53 
54  ~HeavyweightLeakedObjectDetector() { getBacktraceMap().erase (this); }
55 
56 private:
57  //==============================================================================
58  typedef std::map<HeavyweightLeakedObjectDetector<OwnerClass>*, String> BacktraceMap;
59 
60  //==============================================================================
61  struct BacktraceMapHolder
62  {
63  BacktraceMapHolder() = default;
64 
65  ~BacktraceMapHolder()
66  {
67  if (map.size() > 0)
68  {
69  DBG ("*** Leaked objects detected: " << map.size() << " instance(s) of class " << getLeakedObjectClassName());
70  DBG (getFormattedBacktracesString());
71 
72  /** If you hit this, then you've leaked one or more objects of the type specified by
73  the 'OwnerClass' template parameter - the name and stack trace of its creation should
74  have been printed by the lines above.
75 
76  If you're leaking, it's probably because you're using old-fashioned, non-RAII techniques for
77  your object management. Tut, tut. Always, always use std::unique_ptrs, OwnedArrays,
78  ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
79  */
80  jassertfalse;
81  }
82  }
83 
84  String getFormattedBacktracesString() const
85  {
86  String str;
87 
88  int counter = 1;
89  for (auto& bt : map)
90  {
91  str << "\nBacktrace " << String (counter++) << "\n"
92  << "-----------------------------------------------------------------" << "\n"
93  << bt.second;
94  }
95 
96  return str;
97  }
98 
99  BacktraceMap map;
100  };
101 
102  static BacktraceMap& getBacktraceMap()
103  {
104  static BacktraceMapHolder holder;
105  return holder.map;
106  }
107 
108  static const char* getLeakedObjectClassName()
109  {
110  return OwnerClass::getLeakedObjectClassName();
111  }
112 };
113 
114 //==============================================================================
115 #if DOXYGEN || ! defined (JUCE_HEAVYWEIGHT_LEAK_DETECTOR)
116  #if (DOXYGEN || JUCE_CHECK_MEMORY_LEAKS)
117  /** This macro lets you embed a heavyweight leak-detecting object inside a class.
118 
119  To use it, simply declare a JUCE_HEAVYWEIGHT_LEAK_DETECTOR (YourClassName) inside a private section
120  of the class declaration. E.g.
121 
122  @code
123  class MyClass
124  {
125  public:
126  MyClass();
127  void blahBlah();
128 
129  private:
130  JUCE_HEAVYWEIGHT_LEAK_DETECTOR (MyClass)
131  };
132  @endcode
133 
134  NB: you should only use this when you really need to track down a tricky memory leak, and
135  should never leave one of these inside a class!
136 
137  @see HeavyweightLeakedObjectDetector, JUCE_LEAK_DETECTOR, LeakedObjectDetector
138  */
139  #define JUCE_HEAVYWEIGHT_LEAK_DETECTOR(OwnerClass) \
140  friend class juce::HeavyweightLeakedObjectDetector<OwnerClass>; \
141  static const char* getLeakedObjectClassName() noexcept { return #OwnerClass; } \
142  juce::HeavyweightLeakedObjectDetector<OwnerClass> JUCE_JOIN_MACRO (leakDetector, __LINE__);
143  #else
144  #define JUCE_HEAVYWEIGHT_LEAK_DETECTOR(OwnerClass)
145  #endif
146 #endif
147 
148 } // namespace juce
149 
150 /** @}*/
This class is a useful way of tracking down hard to find memory leaks when the regular LeakedObjectDe...
The JUCE String class!
Definition: juce_String.h:42
static String getStackBacktrace()
Returns a backtrace of the current call-stack.