From 0361ecf18c23bbdc5cbaa23cff88a4db1bf061d4 Mon Sep 17 00:00:00 2001
From: Pantelis Lekakis
Date: Fri, 3 Nov 2023 23:38:12 +0000
Subject: [PATCH] Fix for false-positive memory leak when using leak detection
methods (such as CRT dump memory leaks). Since we cannot rely on static
de-initialisation for freeing the registry::s_instance, this is now lazily
allocated instead and freed during spdlog::shutdown() function. In my test
case, saves ~15 reported memory leaks.
---
include/spdlog/details/registry-inl.h | 19 ++++++++++++++++---
include/spdlog/details/registry.h | 8 +++++++-
include/spdlog/spdlog-inl.h | 5 ++++-
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/include/spdlog/details/registry-inl.h b/include/spdlog/details/registry-inl.h
index da4a7de9..596a11c5 100644
--- a/include/spdlog/details/registry-inl.h
+++ b/include/spdlog/details/registry-inl.h
@@ -30,6 +30,9 @@
namespace spdlog {
namespace details {
+registry* registry::s_instance = nullptr;
+std::mutex registry::s_instanceMutex;
+
SPDLOG_INLINE registry::registry()
: formatter_(new pattern_formatter()) {
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
@@ -237,9 +240,19 @@ SPDLOG_INLINE void registry::set_levels(log_levels levels, level::level_enum *gl
}
}
-SPDLOG_INLINE registry ®istry::instance() {
- static registry s_instance;
- return s_instance;
+SPDLOG_INLINE void registry::free() {
+ std::lock_guard lock(s_instanceMutex);
+
+ delete s_instance;
+ s_instance = nullptr;
+}
+
+SPDLOG_INLINE registry ®istry::instance() {
+ std::lock_guard lock(s_instanceMutex);
+ if (s_instance == nullptr) {
+ s_instance = new registry();
+ }
+ return *s_instance;
}
SPDLOG_INLINE void registry::apply_logger_env_levels(std::shared_ptr new_logger) {
diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h
index 56a6886e..46c103e4 100644
--- a/include/spdlog/details/registry.h
+++ b/include/spdlog/details/registry.h
@@ -90,7 +90,10 @@ public:
static registry &instance();
- void apply_logger_env_levels(std::shared_ptr new_logger);
+ // explicitely free the singleton instance.
+ static void free();
+
+ void apply_logger_env_levels(std::shared_ptr new_logger);
private:
registry();
@@ -112,6 +115,9 @@ private:
std::shared_ptr default_logger_;
bool automatic_registration_ = true;
size_t backtrace_n_messages_ = 0;
+
+ static registry* s_instance;
+ static std::mutex s_instanceMutex;
};
} // namespace details
diff --git a/include/spdlog/spdlog-inl.h b/include/spdlog/spdlog-inl.h
index 97c36222..789a900c 100644
--- a/include/spdlog/spdlog-inl.h
+++ b/include/spdlog/spdlog-inl.h
@@ -67,7 +67,10 @@ SPDLOG_INLINE void drop(const std::string &name) { details::registry::instance()
SPDLOG_INLINE void drop_all() { details::registry::instance().drop_all(); }
-SPDLOG_INLINE void shutdown() { details::registry::instance().shutdown(); }
+SPDLOG_INLINE void shutdown() {
+ details::registry::instance().shutdown();
+ details::registry::free();
+}
SPDLOG_INLINE void set_automatic_registration(bool automatic_registration) {
details::registry::instance().set_automatic_registration(automatic_registration);