列表析构函数导致线程本地单例类崩溃

时间:2019-06-26 13:54:25

标签: c++ list c++11 mingw thread-local-storage

我试图用std::list类型的成员创建线程局部单例类。在使用多线程测试我的解决方案期间,我遇到了std::list析构函数(更确切地说,是_M_clear()由析构函数调用的方法)引起的崩溃。即使没有对提到的列表执行任何操作,它也会发生。更奇怪的是,此崩溃是随机发生的。

任何想法,这里可能有什么问题?

以下是减少此错误的最小示例:

#include <list>
#include <thread>

class tls_list_test
{
private:
    std::list<int> test_list;

    tls_list_test() = default;

    ~tls_list_test() = default;

public:
    static tls_list_test& get_instance()
    {
        thread_local tls_list_test instance;
        return instance;
    }
};

int main()
{
    std::list<std::thread> threads;

    for (int i = 0; i < 3; ++i)
    {
        std::thread thread([]()
           {
               auto& instance = tls_list_test::get_instance();
           });
        threads.push_back(std::move(thread));
    }

    for (auto& thread : threads)
    {
        thread.join();
    }

    return 0;
}

std::list中的代码会导致段错误:

  template<typename _Tp, typename _Alloc>
    void
    _List_base<_Tp, _Alloc>::
    _M_clear() _GLIBCXX_NOEXCEPT
    {
      typedef _List_node<_Tp>  _Node;
      __detail::_List_node_base* __cur = _M_impl._M_node._M_next;
      while (__cur != &_M_impl._M_node)
    {
      _Node* __tmp = static_cast<_Node*>(__cur);
      __cur = __tmp->_M_next; // <- SEGFAULT on this line
      _Tp* __val = __tmp->_M_valptr();
#if __cplusplus >= 201103L
      _Node_alloc_traits::destroy(_M_get_Node_allocator(), __val);
#else
      _Tp_alloc_type(_M_get_Node_allocator()).destroy(__val);
#endif
      _M_put_node(__tmp);
    }
    }

GDB变量:

Signal = SIGSEGV (Segmentation fault)
__tmp = {std::__cxx11::_List_base<int, std::allocator>::_Node * | 0xfeeefeeefeeefeee} 0xfeeefeeefeeefeee
__val = {int * | 0x2ee4448} 0x2ee4448
this = {std::__cxx11::_List_base<int, std::allocator> * const | 0x2ee5be8} 0x2ee5be8
__cur = {std::__detail::_List_node_base * | 0xfeeefeeefeeefeee} 0xfeeefeeefeeefeee

G ++版本:

g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0

2 个答案:

答案 0 :(得分:0)

唯一可能的原因是在编译器上实现const exec = require('child_process').exec; let data; const command = "df -g | awk '$4+0 >= 80 { print $4, $7 }' | sort -n"; let exe = exec("ssh user@sistemName " + command, function (error, data, stderr ) { }); console.log(data); 。本地变量不是(暗示)thread_local。尝试将static添加到(本地)变量中:

static

答案 1 :(得分:0)

在8.4之前的所有gcc版本中,都有一个bug用于处理本地函数thread_local

使用较新的gcc版本,或者使用类静态或命名空间范围为thread_local的类。