C++ 分离线程:在没有活动异常的情况下调用终止

问题描述

我正在用 C++ 创建一个线程池系统,但在销毁我的所有线程时出现了一个奇怪的异常。这是正在发生的事情:

terminate called without an active exception

这是我的 Worker 类的代码

  Queue<Job> Worker::job_queue = Queue<Job>();
  std::atomic<bool> Worker::run(false);
  std::vector<Worker*> Worker::workers = std::vector<Worker*>();
  std::mutex Worker::queue_mutex;

  Worker::Worker() : worker_thread(Worker::loop,this){
    worker_thread.detach();
    workers.push_back(this);
  }

  void Worker::loop(){
    while(Worker::run){
      try{
        queue_mutex.lock();
        Job todo = job_queue.pop();
        queue_mutex.unlock();
        todo.job(todo.params);
        todo.isDone = true;
      } catch(...){
        queue_mutex.unlock();
      }
    }
  }

  void Worker::init(){ //Static method; called when the program starts
    run = true;
    for(int i=0;i<NUM_OF_WORKERS;i++){
      workers.push_back(new Worker());
    }
  }

  void Worker::uninit(){ //Static method; called when the program is about to terminate
    run = false;
    for(int i=0;i<workers.size();i++){
      delete workers[i];
    }
  }

为什么会发生这种情况,我该如何解决

解决方法

  1. 您将同一个对象插入 workers 两次 - 首先是在 Worker() 构造函数中,然后是在 operator new 返回时。所以最后,你得到了双重自由——你应该使用带有智能指针的 RAII。

  2. 您正在手动锁定和解锁互斥锁,并拦截并吞下所有异常 - 您应该使用带有 ::std::lock 对象的 RAII。

  3. 分离线程通常不是一个好主意,请参阅When should I use std::thread::detach?。销毁那些线程仍在使用的对象会导致麻烦。