2016-12-29 85 views
0

我有一個處理多線程C++代碼中的異常的問題。以下程序以terminate called without an active exception Aborted (core dumped)退出。std ::線程和異常處理

#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(); 
    } 
} 

相反,我想處理異常的try catchmain()。我知道異常不會(通常)在線程之間傳遞,因爲線程每個都有自己的堆棧。這裏的問題(在我看來)是即使在非分叉線程上生成異常也沒有被處理。如果我註釋掉run()control_thread有關的行,那麼一切正常。

與鏗鏘-3.8和-std=c++11 main.cpp -lpthread編譯。

+0

@Curious也許。我知道'exception_ptr'。但這裏的問題(我認爲)是thrower(runComponent)實際上是在主線程上。即使在這種情況下,我是否需要使用異常指針? – jonnew

+0

在下面的答案中回答!我誤解了這個問題 – Curious

回答

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(); 
    } 
} 

它看起來就像你想要的是一個分離的東西,這就是爲什麼我脫離線程在上面的例子。如果這不是你想要的,你可能需要一些其他方式來處理線程。如果你想讓主線程和其他線程獨立工作,那麼你需要一些其他的同步。

+0

是的,這是有效的。我想我想要分離,但我注意到在你提供的SO鏈接的答案中提出的觀點「除非你需要更多的靈活性,並且願意提供一個同步機制來等待你自己的線程完成,其中你可能會使用分離「。在這個特殊情況下,這是什麼意思?如果我使用detach,會釋放'runController()'分配的資源嗎? – jonnew

+0

此外,「C++線程錯誤」是否指標準庫實現? – jonnew

+0

@jonnew我認爲這意味着如果你想要一些自定義的方式來處理異常,那麼你將不得不手動使用鎖來實現它。最簡單的事情是按照發生異常的順序創建一個線程列表,其中包含線程的線程標識符。我不認爲這是相關 – Curious