终止调用递归 C++ 多线程

Posted

技术标签:

【中文标题】终止调用递归 C++ 多线程【英文标题】:terminate called recursively c++ multithreading 【发布时间】:2020-07-21 08:51:34 【问题描述】:

我是线程新手,遇到了让我困惑的情况,我尝试在放入线程的函数中抛出异常,在 main() 函数中我有一个 try 和 catch 块,但是我仍然得到这些错误:

1. terminate called after throwing an instance of 'char const*'

2. terminate called recursively

下面是我的代码

mutex m;

void AccumulateRange(uint64_t &sum, uint64_t start, uint64_t end) 
    for (uint64_t i = start;i<end;++i)
        sum+=i;
        if (sum>10) 
            throw "Number Exceed";
    


int main()

    const uint64_t num_threads = 1000;
    uint64_t nums = 1000*1000*1000;
    vector<uint64_t> v(num_threads);
    vector<thread> threads;
    uint64_t steps = nums/num_threads;

    for (uint64_t i = 0;i<num_threads;++i)
        try
            threads.push_back(thread(AccumulateRange,ref(v[i]),steps*i,(i+1)*steps));
        
        catch (const char& exception)
            cout<<exception<<endl;
        
    
    for (auto &t : threads)
        if (t.joinable())
           t.join();    
    
    uint64_t total = accumulate(begin(v),end(v),0);
    return 0;

提前致谢!

【问题讨论】:

您的 try catch 可能会在线程创建时抛出异常时捕获,但不会在线程执行时捕获。 不要扔任何不是std::exception的东西 @LouisGo 你说的“try catch 可能会在线程创建时抛出异常时捕获”是什么意思,这是怎么发生的? @pptaszni 你能给我更多的细节或参考你所说的吗?我想了解更多。 @Delta 已经解释过了。你尝试catch只能捕获创建线程中的异常,即std::system_error,而线程无法启动。 reference。一旦创建线程,线程中的异常必须在线程中捕获,因为线程有自己的堆栈。或者使用 pptaszni 的建议。 【参考方案1】:

详细说明@DeltA 答案:您可以使用std::future,而不是使用std::thread 并使用指针传递异常,因为它将抛出的异常存储在其共享状态中:

void AccumulateRange(uint64_t& sum, uint64_t start, uint64_t end)

    for (uint64_t i = start; i < end; ++i)
    
        sum += i;
        if (sum > 10)
            throw std::runtime_error("Number Exceed");
    


int main()

    const uint64_t num_threads = 1000;
    uint64_t nums = 1000 * 1000 * 1000;
    std::vector<uint64_t> v(num_threads);
    std::vector<std::future<void>> futures;
    uint64_t steps = nums / num_threads;
    for (uint64_t i = 0; i < num_threads; ++i)
    
        futures.push_back(std::async(std::launch::async, AccumulateRange, std::ref(v[i]), steps * i, (i + 1) * steps));
    
    for (auto& f : futures)
    
        try
        
            f.get();
        
        catch (const std::exception& e)
        
            std::cout << e.what() << std::endl;
        
    

【讨论】:

谢谢!我会调查它,但在此之前,我想知道为什么不再需要 join()? 因为std::future 没有join。相反,它有get,其行为方式类似。 future, async.【参考方案2】:

您无法在线程之间捕获异常。当一个异常被抛出时,调用栈被展开,寻找一个catch。每个线程都有自己的堆栈。 另一种方法是使用某种全局变量或队列或其他机制将异常从工作线程传递到主线程。 检查这个Catching exception from worker thread in the main thread

【讨论】:

以上是关于终止调用递归 C++ 多线程的主要内容,如果未能解决你的问题,请参考以下文章

C++多线程强制终止

C++多线程编程——线程的挂起唤醒与终止

C++多线程强制终止

C++多线程强制终止

多线程递归程序c++

如何安全地终止线程? (使用指针)C++