【问题标题】:std::thread and exception handlingstd::thread 和异常处理
【发布时间】:2017-05-13 09:15:12
【问题描述】:

我在处理多线程 C++ 代码中的异常时遇到问题。以下程序以terminate called without an active exception Aborted (core dumped) 退出。

#include <thread>
#include <iostream>
#include <stdexcept>

struct Thing {

    void runComponent()
    {
       throw std::runtime_error("oh no!\n");
    }

    void runController()
    {
        while (true) {}
    }

    void run()
    {
        auto control_thread = std::thread([this] { runController(); });

        runComponent();

        if (control_thread.joinable())
            control_thread.join();
    }
};

int main() 
{
    try {
        Thing thing;
        thing.run();
    } catch (std::runtime_error &ex) {
        std::cerr << ex.what();
    }
}

相反,我想处理main()try catch 块中的异常。我知道异常不会(通常)在线程之间传递,因为每个线程都有自己的堆栈。这里的问题(在我看来)是异常没有被处理,即使它是在非分叉线程上生成的。如果我将run() 中与control_thread 相关的行注释掉,一切正常。

使用 clang-3.8 和 -std=c++11 main.cpp -lpthread 编译。

【问题讨论】:

  • @Curious 也许。我知道exception_ptr。但是这里的问题(我认为..)是 thrower (runComponent) 实际上在主线程上。即使在这种情况下,我还需要使用异常指针吗?
  • 在下面的答案中回答!我误解了这个问题

标签: c++ multithreading exception


【解决方案1】:

这里的问题是您既没有在run() 方法中创建的线程上调用detach()join()。这是 C++ 线程中的错误。见When should I use std::thread::detach?

如果您将代码更改为以下任何一种,则一切正常

#include <thread>
#include <iostream>
#include <stdexcept>

struct Thing {

    void runComponent()
    {
       throw std::runtime_error("oh no!\n");
    }

    void runController()
    {
        return;
    }

    void run()
    {
        auto control_thread = std::thread([this] { runController(); });
        // either of the following two will work
        // control_thread.join();
        control_thread.detach();

        runComponent();
    }
};

int main()
{
    try {
        Thing thing;
        thing.run();
    } catch (std::runtime_error &ex) {
        std::cerr << ex.what();
    }
}

看起来你想要的是一个分离,这就是我在上面的例子中分离线程的原因。如果这不是您想要的,您可能需要其他方式来处理线程的join()ing。如果您希望主线程和其他线程独立运行,那么您将需要其他一些同步。

【讨论】:

  • 是的,这行得通。我想我确实想要分离,但我注意到您提供的 SO 链接的答案中提出的观点“除非您需要更大的灵活性并且愿意提供一种同步机制来自己等待线程完成,其中如果你可以使用分离”。在这种特殊情况下,这意味着什么? runController()分配的资源如果使用detach会被释放吗?
  • 另外,“c++ 线程中的错误”是指标准库实现中的意思吗?
  • @jonnew 我认为这意味着如果您想要一些自定义方式来处理异常,那么您将不得不使用锁手动实现它。最简单的事情是创建一个线程列表,其中按照发生异常的顺序具有线程的线程 ID。我不认为这是相关的
  • @jonnew,std::thread 析构函数检查以确保用户调用了detachjoin,如果两者都没有被调用,则终止程序。所以我猜是的,标准库实现会导致你的程序退出并报错
  • 啊,我明白了。这就说得通了。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-11
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多