2014-03-06 77 views
0

我正在編寫一個應該對給定數據集進行某種處理的程序(實際上是一個庫)。該程序有一個插件機制。每個插件都遵循不同的數據處理策略。這個想法是,用戶可以在插件中創建自己的處理策略,他不必觸摸程序的代碼。該軟件是一個基於服務器的應用程序,它永遠不會終止。問題如下:如果用戶提供了自己的插件,但是他的代碼會拋出未處理的異常呢?這會使應用程序崩潰,服務器將脫機。鑑於插件總是創建一個從類派生可見的庫和插件明顯的解決方案都將是一個對象:從C++的基類中處理重寫方法的異常

class AbstractSolver 
{ 
public: 
    void solve(void) 
    { 
     try { 
     this->solve_impl(); 
     } catch (...) { 
      std::cout << "got exception" << std::endl; 
     } 
    } 
private: 
    virtual void solve_impl(void) = 0; 
}; 

// This is the class of the plugin 
class MySolver : public AbstractSolver 
{ 
private: 
    void solve_impl(void) 
    { 
     throw std::exception(); 
    } 
} 

雖然這是去工作,我不想寫嘗試捕捉AbstractSolver類的每個公共方法的語句。另外,我想避免宏,我更喜歡C++ 11解決方案。我正在考慮引入一個ExceptionGuard類,該類將作爲其構造函數的參數solve_impl方法,並將在那裏執行try/catch。我試圖用std :: function來傳遞方法,但我有點失敗。你必須建議一個更優雅的解決方案嗎?謝謝。

+3

您應該[1]在基類中聲明虛函數爲'noexcept',以防止派生類拋出異常,或者[2]定義一組異常可能會被拋出然後捕獲那些(並使用[異常翻譯器]處理它們(http://blogs.msdn.com/b/vcblog/archive/2014/01/16/exception-boundaries.aspx)。 catch'...';你不知道什麼可能出錯或者系統的狀態 –

+0

我不太確定noexcept是什麼,但是如果我把虛函數聲明爲noexcept,什麼都不會改變。 – AstrOne

+1

聲明虛函數hook noexcept並不能真正解決OP的問題如果沒有'try' /'catch'塊,應用程序崩潰是因爲插件拋出一個未處理的異常。 'noexcept',應用程序崩潰,因爲插件違反了異常規範,運行時調用'terminate()'。 –

回答

1

What if the user provides his own plugin but his code throws an unhanded exception? This will make the application to crash and the server will go offline.

如果用戶提供的插件拋出未由插件規範所允許的異常,那麼就是在用戶提供的插件中的邏輯錯誤。檢測到邏輯錯誤時要做的正確事情是立即停止執行並終止進程(可能在最終嘗試記錄失敗或向系統中的其他組件通知即將終止的最終嘗試之後)。

你可能會問「如果用戶提供自己的插件,但他的代碼通過空指針執行間接尋址?」或者「如果用戶提供他自己的插件,但是他的代碼進入無限循環或導致死鎖並永不返回?」邏輯錯誤是一個邏輯錯誤:當你檢測到它時,你無法知道進程的狀態以及繼續執行是否安全。

如果插件不能拋出異常,請在基類中聲明虛函數noexcept。這將需要派生類中的所有重寫爲noexcept。如果重寫未能處理異常並且該異常在noexcept邊界處泄漏,則將調用std::terminate(),終止執行。如果您需要能夠在終止時重新啓動服務,請考慮使用監視服務的監視程序進程。

對於在異常邊界處理異常的更一般問題,請考慮使用異常轉換器幷包裝可能會拋入lambda表達式的代碼。我寫了一篇關於此的詳細文章:"Exception Boundaries."