程序退出时,static thread_local std :: unique_ptr崩溃

时间:2014-10-15 19:12:26

标签: c++ multithreading unique-ptr thread-local-storage

我有一个线程本地单例类,看起来有点像这样:

// 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();
}

我需要为实例使用动态分配,因为必须在我的程序中完成其他步骤后创建UserActionManager。

当我运行程序时,它可以正常运行,直到程序退出。我收到这样的错误:

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

如果我在lldb中运行程序,我收到此消息,告诉我在我的thread_local UserActionManager实例的默认删除调用中发生了崩溃。

// lldb输出

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

但是,如果你查看线程本地实例的代码打印的指针和未被分配的释放指针,它们就不一样了:

//由GetUserActionManager()打印的指针:

0x7fc650948300
0x7fc64a4de670
0x7fc650b33480
0x7fc650c19f90

//导致崩溃的指针:

0x7fc64ce79460
0x7fc64ce7b140
0x7fc64ce7b8e0

这里发生了什么?我过去使用过这段代码没有问题。现在我在MacOSX和c ++ 14上使用g ++ 4.9.1并且崩溃了。永远不会调用UserActionManager的析构函数,默认删除尝试释放的指针与它应该具有的指针不同。我已经使用了grepped代码,这只是在创建它的静态方法中引用了Instance,所以我不认为这是来自其他地方的副作用。如果我为实例使用原始指针,代码工作正常。

有关如何解决此问题的任何建议?谢谢!

编辑:

我刚刚发现了这个:

Why global or static object can lead to crash when program exit?

UserActionManager现在是库的一部分,程序&#34;简单&#34;是链接到它。以前(当这个工作时)我将代码编译为一个整体。这会导致问题吗?&#34;

0 个答案:

没有答案