【问题标题】:Does exception belong to threads or process in C++?异常是否属于 C++ 中的线程或进程?
【发布时间】:2018-11-01 15:05:12
【问题描述】:

假设我们有两个正在运行的线程,它们都会抛出异常,并且这些线程中有异常处理程序。 C++ 是否能够处理这个问题,而不会遇到终止或未定义的行为。

异常属于每个线程,每个线程一次只能有一个异常,对吗?

【问题讨论】:

  • 您是否捕捉任何异常?
  • @KerrekSB 是的。已编辑
  • 如何将这个问题复制为“将 main() 捕获线程抛出的异常?”
  • 我不知道。我要重新营业了。
  • 将异常视为函数调用返回的另一种方式。调用/返回发生在单个线程的堆栈上。例外情况也是如此。 (注意:如果 top-level 函数在其多个线程之一中抛出,我还不足以知道多线程进程应该发生什么。)

标签: c++ multithreading exception


【解决方案1】:

异常属于每个线程是否正确

没错。

每个线程一次只能有一个异常?

一个线程可以有多个活动异常。见int uncaught_exceptions() noexcept

检测当前线程中有多少异常已被抛出或重新抛出,但尚未进入其匹配的 catch 子句。

例如:

#include <iostream>
#include <stdexcept>

void f() {
    throw std::runtime_error("error");
}

struct A {
    ~A() {
        std::cout << "uncaught_exceptions: " << std::uncaught_exceptions() << '\n';
    }
};

struct B {
    ~B() {
        try {
            A a;
            f();
        }
        catch(std::exception&) {}
    }
};

int main() {
    try {
        B b;
        f();
    }
    catch(std::exception&) {}
}

输出:

uncaught_exceptions: 2

【讨论】:

    【解决方案2】:

    以下示例显示异常处理程序正在使用线程 t1 的堆栈,该堆栈进行了零除异常。这意味着异常属于每个线程。

    // g++ -std=c++0x -pthread -fnon-call-exceptions main.cpp
    #include <iostream>
    #include <thread>
    #include <signal.h>
    
    void handler(int signo) {
        int handler_local_var;
        std::cout << &handler_local_var << " in stack of handler" << std::endl;
        throw signo;
    }
    
    void thread1(std::string msg) {
        int t1_local_var;
        std::cout << &t1_local_var << " in stack of " << msg << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        signal(SIGFPE,handler);
        try { 
            int x = 100 / 0; /* ignore warning: division by zero [-Wdiv-by-zero] */
        }
        catch (...) {
            std::cout << "caught" << std::endl;
        }
        while (1) {
            std::this_thread::sleep_for(std::chrono::seconds(2));
        }
    }
    
    void thread2(std::string msg) {
        int t2_local_var;
        std::cout << &t2_local_var << " in stack of " << msg <<  std::endl;
        while (1) {
            std::this_thread::sleep_for(std::chrono::seconds(2));
        }
    }
    
    int main() {
        int main_local_var;
        std::cout << &main_local_var << " in stack of main" << std::endl;
        std::thread t1(thread1,"t1");
        std::thread t2(thread2,"t2");
        while (1) {
            std::this_thread::sleep_for(std::chrono::seconds(2)); /* Ctrl-C to stop */
        }
        return 0;
    }
    

    测试结果:

    $ ./a.out 
    0x7ffee7fea788 in stack of main
    0x7f0b54b92d68 in stack of t2
    0x7f0b55393d54 in stack of t1
    0x7f0b55393754 in stack of handler
    caught
    

    【讨论】:

    • 来自信号处理程序的throw 合法吗?
    • 选项-fnon-call-exceptions 允许它。我的代码 sn-p 仅用于测试目的。
    • 好的,检查完毕。
    猜你喜欢
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2017-08-14
    相关资源
    最近更新 更多