From dff1d8b2a4e86e88f4416a6cb38461c2558f3cb6 Mon Sep 17 00:00:00 2001 From: Victor Zarubkin Date: Mon, 17 Apr 2017 23:31:07 +0300 Subject: [PATCH] (Core) Update #29 : fixed potential memory leak for NonscopedBlock + linux build --- easy_profiler_core/profile_manager.cpp | 9 +++++++-- easy_profiler_core/profile_manager.h | 26 ++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/easy_profiler_core/profile_manager.cpp b/easy_profiler_core/profile_manager.cpp index 0868217..56df36c 100644 --- a/easy_profiler_core/profile_manager.cpp +++ b/easy_profiler_core/profile_manager.cpp @@ -260,7 +260,7 @@ extern "C" { #elif defined(USE_STD_CHRONO) return _ticks; #else - return _ticks / CPU_FREQUENCY.load(std::memory_order_acquire) + return _ticks / CPU_FREQUENCY.load(std::memory_order_acquire); #endif } @@ -271,7 +271,7 @@ extern "C" { #elif defined(USE_STD_CHRONO) return _ticks / 1000; #else - return _ticks * 1000 / CPU_FREQUENCY.load(std::memory_order_acquire) + return _ticks * 1000 / CPU_FREQUENCY.load(std::memory_order_acquire); #endif } @@ -610,6 +610,11 @@ void NonscopedBlock::copyname() } } +void NonscopedBlock::destroy() +{ + m_runtimeName.std::string::~string(); // free memory used by m_runtimeName +} + ////////////////////////////////////////////////////////////////////////// ThreadStorage::ThreadStorage() : nonscopedBlocks(16), id(getCurrentThreadId()), allowChildren(true), named(false), guarded(false) diff --git a/easy_profiler_core/profile_manager.h b/easy_profiler_core/profile_manager.h index 47ff39b..ac12680 100644 --- a/easy_profiler_core/profile_manager.h +++ b/easy_profiler_core/profile_manager.h @@ -306,10 +306,23 @@ public: */ void copyname(); + void destroy(); + }; // END of class NonscopedBlock. ////////////////////////////////////////////////////////////////////////// +template +inline void destroy_elem(T*) +{ + +} + +inline void destroy_elem(NonscopedBlock* _elem) +{ + _elem->destroy(); +} + template class StackBuffer { @@ -329,7 +342,13 @@ public: ~StackBuffer() { + for (uint32_t i = 0; i < m_size; ++i) + destroy_elem(m_buffer + i); + free(m_buffer); + + for (auto& elem : m_overflow) + destroy_elem(reinterpret_cast(elem.data + 0)); } template @@ -351,9 +370,11 @@ public: if (m_overflow.empty()) { // m_size should not be equal to 0 here because ProfileManager behavior does not allow such situation - if (--m_size == 0 && m_maxcapacity > m_capacity) + destroy_elem(m_buffer + --m_size); + + if (m_size == 0 && m_maxcapacity > m_capacity) { - // When stack gone empty we can resize buffer to use enough space in future + // When stack gone empty we can resize buffer to use enough space in the future free(m_buffer); m_maxcapacity = m_capacity = std::max(m_maxcapacity, m_capacity << 1); m_buffer = (T*)malloc(m_capacity * sizeof(T)); @@ -362,6 +383,7 @@ public: return; } + destroy_elem(reinterpret_cast(m_overflow.back().data + 0)); m_overflow.pop_back(); }