C++ boost线程在实例化两次时导致分段错误

Posted

技术标签:

【中文标题】C++ boost线程在实例化两次时导致分段错误【英文标题】:C++ boost thread causes segmentation fault when instantiated twice 【发布时间】:2017-05-04 15:08:47 【问题描述】:

我有一个在构造时运行后台任务的类(请参阅构造函数)。然后停止此任务,并在对象被销毁时将线程加入析构函数中:

// Foo.hpp -------------------------------
#include <boost/thread.hpp>
#include <boost/date_time/posix_time.hpp>

class Foo 
  boost::thread theThread;

  Foo();
  ~Foo();
  void bar() const;


// Foo.cpp -------------------------------
// This is the background task.
void Foo::bar() const 
  while (true) 
    try 
      // sleep for 1 minute.
      boost:this_thread_sleep(boost::posix_time::minutes(1));

      // do other stuff endlessly
    

    // boost interrupt was called, stop the main loop.
    catch (const boost::thread_interrupted&)
    
      break;
    


// Instantiate background task
Foo::Foo()
    : theThread(&Foo::bar, this)

    // do other stuff


// Stop background task
Foo::~Foo() 
    theThread.interrupt()
    theThread.join();

现在,当我有一个类的单个实例时,这可以正常工作:

// main.cpp
Foo f;
// do other stuff with f

但是当我这样做时,我得到一个分段错误和一个中止的消息:

// main.cpp
Foo *f;
f = new Foo(); // causes seg fault
delete f;

为什么?

【问题讨论】:

boost::thread 是否尝试取消引用其构造函数中的第二个参数(在您的情况下为 this)?如果是这样,那么在初始化列表中使用this 作为参数似乎并不安全。 不确定是否在将 foo::bar 提供给线程时构建了它 抱歉,您的代码无法编译,并且您的析构函数是私有的,因此您无法在 main.cpp 中实例化此类。您确定此代码重现了您的问题吗? 【参考方案1】:

Xcode 报错:

尝试使用已删除的函数

Foo::Bar 不能用上面的语法调用(&Foo::Bar),因为它不是一个静态函数。它有一个隐藏的这个参数,导致签名不匹配。

更多信息在这里: pthread function from a class

在初始化列表上使用成员函数也是不好的做法,行为是未定义的。在此引用:

可以调用成员函数(包括虚成员函数) 来自成员初始值设定项,但行为未定义(如果不是全部) 直接基在此时初始化。

http://en.cppreference.com/w/cpp/language/initializer_list

以下作品:

   void bar(atomic_int*exit) 
    while (*exit) 
        // sleep for 1 minute.
        this_thread::sleep_for(std::chrono::seconds(2));

        // do other stuff endlessly

    


class Foo 
    thread theThread;
    atomic_int _exit;

public:
   // Instantiate background task
    Foo(): _exit(1)
    
        // do other stuff
        init();
    
    void init()
    
        theThread = std::thread (&bar,&_exit);
    

    // Stop background task
    ~Foo() 
        _exit = 0;
        theThread.join();
    
;

【讨论】:

我的 c++ 版本中没有 std::thread 或 atomic 类型,对不起,兄弟,不起作用。 抱歉,我不使用 boost,但如果您想进一步了解,它确实有 boost::atomic。在任何情况下,您都不能以这种方式传递成员函数,需要将其外部化或使其成为静态。

以上是关于C++ boost线程在实例化两次时导致分段错误的主要内容,如果未能解决你的问题,请参考以下文章

Flask-Mail Mail()实例化两次

join() 上的 Boost 线程分段错误

C++ 11 Boost 1.65 recursive_directory_iterator 给出分段错误错误

Boost 线程中的分段错误 tls_destructor

notify_all 导致分段错误

Pthread_create 在 C++ 中导致分段错误