]> granicus.if.org Git - icinga2/commitdiff
Improve debug support for analyzing memory leaks
authorGunnar Beutner <gunnar@beutner.name>
Tue, 19 Jan 2016 14:24:17 +0000 (15:24 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 23 Feb 2016 08:57:49 +0000 (09:57 +0100)
refs #10963

lib/base/object.cpp
lib/base/object.hpp

index 821d1104797a5bf78bb807c24acb5a7767dfb3a1..1a6d1c9ab647b3fa6bfcaaca2180a22e94b3b0da 100644 (file)
 #include "base/dictionary.hpp"
 #include "base/primitivetype.hpp"
 #include "base/utility.hpp"
+#include "base/timer.hpp"
+#include "base/logger.hpp"
+#include <boost/foreach.hpp>
 
 using namespace icinga;
 
 DEFINE_TYPE_INSTANCE(Object);
 
+#ifdef I2_DEBUG
+static boost::mutex l_ObjectCountLock;
+static std::map<String, int> l_ObjectCounts;
+static Timer::Ptr l_ObjectCountTimer;
+#endif
+
 /**
  * Default constructor for the Object class.
  */
@@ -117,3 +126,45 @@ Type::Ptr Object::GetReflectionType(void) const
        return Object::TypeInstance;
 }
 
+#ifdef I2_DEBUG
+void icinga::TypeAddObject(Object *object)
+{
+       boost::mutex::scoped_lock lock(l_ObjectCountLock);
+       String typeName = Utility::GetTypeName(typeid(*object));
+       l_ObjectCounts[typeName]++;
+}
+
+void icinga::TypeRemoveObject(Object *object)
+{
+       boost::mutex::scoped_lock lock(l_ObjectCountLock);
+       String typeName = Utility::GetTypeName(typeid(*object));
+       l_ObjectCounts[typeName]--;
+}
+
+static void TypeInfoTimerHandler(void)
+{
+       boost::mutex::scoped_lock lock(l_ObjectCountLock);
+
+       typedef std::map<String, int>::value_type kv_pair;
+       BOOST_FOREACH(kv_pair& kv, l_ObjectCounts) {
+               if (kv.second == 0)
+                       continue;
+
+               Log(LogInformation, "TypeInfo")
+                   << kv.second << " " << kv.first << " objects";
+
+               kv.second = 0;
+       }
+}
+
+static void StartTypeInfoTimer(void)
+{
+       l_ObjectCountTimer = new Timer();
+       l_ObjectCountTimer->SetInterval(10);
+       l_ObjectCountTimer->OnTimerExpired.connect(boost::bind(TypeInfoTimerHandler));
+       l_ObjectCountTimer->Start();
+}
+
+INITIALIZE_ONCE(StartTypeInfoTimer);
+#endif /* I2_DEBUG */
+
index 6d7b3baf6950dfc85920a7e27114c3e59d2e4eef..3001e4a69d0f1da7e25af9877fe886bd302815cc 100644 (file)
@@ -134,8 +134,16 @@ private:
        friend void intrusive_ptr_release(Object *object);
 };
 
+void TypeAddObject(Object *object);
+void TypeRemoveObject(Object *object);
+
 inline void intrusive_ptr_add_ref(Object *object)
 {
+#ifdef I2_DEBUG
+       if (object->m_References == 0)
+               TypeAddObject(object);
+#endif /* I2_DEBUG */
+
 #ifdef _WIN32
        InterlockedIncrement(&object->m_References);
 #else /* _WIN32 */
@@ -153,8 +161,13 @@ inline void intrusive_ptr_release(Object *object)
        refs = __sync_sub_and_fetch(&object->m_References, 1);
 #endif /* _WIN32 */
 
-       if (refs == 0)
+       if (refs == 0) {
+#ifdef I2_DEBUG
+               TypeRemoveObject(object);
+#endif /* I2_DEBUG */
+
                delete object;
+       }
 }
 
 template<typename T>