I have a local single-threaded thread class that looks something like this:
//UserActionManager.hh
class UserActionManager
{
public:
static UserActionManager* GetUserActionManager();
~UserActionManager() { std::cout << "UAM destructor called.\n"; }
static thread_local std::unique_ptr<UserActionManager> theInstance;
};
//UserActionManager.cc
thread_local std::unique_ptr<UserActionManager> UserActionManager::theSafeInstance = nullptr;
UserActionManager*
UserActionManager::
GetUserActionManager()
{
if (nullptr == theInstance)
{
theInstance.reset(new UserActionManager());
std::cout << "theInstance = " << theInstance.get() << "\n";
}
return theInstance.get();
}
I need to use dynamic allocation for the instance because the UserActionManager must be created after the other steps have been completed in my program.
When I run the program, it works fine until the program exits. I get an error message:
simple(57724,0x10b647000) malloc: *** error for object 0x7fc64ce79460: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
simple(57724,0x10d64d000) malloc: *** error for object 0x7fc64ce7b140: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
simple(57724,0x10c64a000) malloc: *** error for object 0x7fc64ce7b8e0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
*** Break *** illegal instruction
*** Break *** illegal instruction
*** Break *** illegal instruction
If I run the program in lldb, I get this message that tells me that the crash occurs by default to delete my thread_local UserActionManager instance.
// lldb output
Process 57201 stopped
* thread #2: tid = 0x8d5d1, 0x0000000105a2eed7 libGex.dylib`std::default_delete<gex::ua::UserActionManager>::operator()(gex::ua::UserActionManager*) const + 27, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000105a2eed7 libGex.dylib`std::default_delete<gex::ua::UserActionManager>::operator()(gex::ua::UserActionManager*) const + 27
libGex.dylib`std::default_delete<gex::ua::UserActionManager>::operator()(gex::ua::UserActionManager*) const + 27:
-> 0x105a2eed7: movq (%rax), %rax
0x105a2eeda: addq $0x48, %rax
0x105a2eede: movq (%rax), %rax
0x105a2eee1: movq -0x10(%rbp), %rdx
However, if you look at pointers printed by code for local instances of the stream, and pointers that are freed without allocation, they do not match:
//, GetUserActionManager():
0x7fc650948300
0x7fc64a4de670
0x7fc650b33480
0x7fc650c19f90
//, :
0x7fc64ce79460
0x7fc64ce7b140
0x7fc64ce7b8e0
? . g++ 4.9.1 MacOSX ++ 14 . UserActionManager , , , , , . grepped , theInstance , , , . , "".
? !
EDIT:
:
?
UserActionManager , "simple" . ( ) . ? "