Skip to content

Commit 9e28518

Browse files
committed
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. # Conflicts: # include/singleton.hpp
1 parent cc273e9 commit 9e28518

1 file changed

Lines changed: 10 additions & 5 deletions

File tree

include/singleton.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ struct Singleton
6464
Instance(const Instance&) = delete;
6565
~Instance()
6666
{
67-
// Destroys the locally-initialized instance. Injected ones are ignored (no ownership).
68-
if (m_pExtern == LOCAL_INSTANCE_ID)
69-
GetBuffer().~T();
67+
DestroyLocalInstance();
7068
}
7169
Instance& operator =(const Instance&) = delete;
7270
/// Returns the current instance.
@@ -75,7 +73,7 @@ struct Singleton
7573
template <typename ...Args>
7674
void Emplace(Args... args)
7775
{
78-
this->~Instance();
76+
DestroyLocalInstance();
7977
new (&GetBuffer()) T(std::forward<Args>(args)...);
8078
m_pExtern = LOCAL_INSTANCE_ID;
8179
}
@@ -84,7 +82,7 @@ struct Singleton
8482
*/
8583
void SetExtern(T* ptr)
8684
{
87-
this->~Instance();
85+
DestroyLocalInstance();
8886
m_pExtern = ptr;
8987
}
9088
private:
@@ -100,6 +98,13 @@ struct Singleton
10098
static union U { T asT; U(){} ~U(){} } buffer;
10199
return buffer.asT;
102100
}
101+
/// Destroys the local instance, while ignoring injected ones (no ownership).
102+
/** @remark This leaves the object in an inconsistent state. m_pExtern must be changed. */
103+
void DestroyLocalInstance()
104+
{
105+
if (m_pExtern == LOCAL_INSTANCE_ID)
106+
GetBuffer().~T();
107+
}
103108
} g_instance;
104109

105110
/// Holds a flag used for `std::call_once()`.

0 commit comments

Comments
 (0)