From abfacd9e56a20024daf6f1f6e27749121eecd303 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 19 Jan 2016 15:24:17 +0100 Subject: [PATCH] Improve debug support for analyzing memory leaks refs #10963 --- lib/base/object.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++ lib/base/object.hpp | 15 ++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lib/base/object.cpp b/lib/base/object.cpp index 821d1104797..1a6d1c9ab64 100644 --- a/lib/base/object.cpp +++ b/lib/base/object.cpp @@ -22,11 +22,20 @@ #include "base/dictionary.hpp" #include "base/primitivetype.hpp" #include "base/utility.hpp" +#include "base/timer.hpp" +#include "base/logger.hpp" +#include using namespace icinga; DEFINE_TYPE_INSTANCE(Object); +#ifdef I2_DEBUG +static boost::mutex l_ObjectCountLock; +static std::map 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::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 */ + diff --git a/lib/base/object.hpp b/lib/base/object.hpp index 6d7b3baf695..3001e4a69d0 100644 --- a/lib/base/object.hpp +++ b/lib/base/object.hpp @@ -134,8 +134,16 @@ class I2_BASE_API Object 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