From 343687b50d50a77d5c86686b609cd04dbd8b230d Mon Sep 17 00:00:00 2001 From: Speeder Date: Sat, 24 Jan 2026 19:51:51 +0100 Subject: [PATCH] Fixed undefined state after Reset/Inject call The instance's Emplace and SetExtern methods called the dtor, which could set the instance into an undefined state. Moved cleanup from the dtor function into a dedicated method to avoid the dtor's object-lifetime ending effect. --- include/singleton.hpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/singleton.hpp b/include/singleton.hpp index 9b34122..3d04dc3 100644 --- a/include/singleton.hpp +++ b/include/singleton.hpp @@ -76,9 +76,7 @@ struct Singleton Instance(const Instance&) = delete; ~Instance() { - // Destroys the locally-initialized instance. Injected ones are ignored (no ownership). - if (m_pExtern == LOCAL_INSTANCE_ID) - GetBuffer().~T(); + DestroyLocalInstance(); } Instance& operator =(const Instance&) = delete; /// Returns the current instance. @@ -91,7 +89,7 @@ struct Singleton template void Emplace(Args&&... args) { - this->~Instance(); + DestroyLocalInstance(); try { new (&GetBuffer()) T(std::forward(args)...); @@ -108,7 +106,7 @@ struct Singleton */ void SetExtern(T* ptr) { - this->~Instance(); + DestroyLocalInstance(); m_pExtern = ptr; } private: @@ -123,6 +121,13 @@ struct Singleton // Static, uninitialized buffer for the singleton's object static union U { T asT; U(){} ~U(){} } buffer; return buffer.asT; + } + /// Destroys the local instance, while ignoring injected ones (no ownership). + /** @remark This leaves the object in an inconsistent state. m_pExtern must be changed. */ + void DestroyLocalInstance() + { + if (m_pExtern == LOCAL_INSTANCE_ID) + GetBuffer().~T(); } } g_instance;