2011-12-21 58 views
3

考慮下面的代碼片段:從標準嵌套的處理程序是否影響異常的生命週期?

struct ExceptionBase : virtual std::exception{}; 
struct SomeSpecificError : virtual ExceptionBase{}; 
struct SomeOtherError : virtual ExceptionBase{}; 

void MightThrow(); 
void HandleException(); 
void ReportError(); 

int main() 
{ 
    try 
    { 
    MightThrow(); 
    } 
    catch(...) 
    { 
    HandleException(); 
    } 
} 

void MightThrow() 
{ 
    throw SomeSpecificError(); 
} 

void HandleException() 
{ 
    try 
    { 
    throw; 
    } 
    catch(ExceptionBase const &) 
    { 
    // common error processing 
    } 

    try 
    { 
    throw; 
    } 
    catch(SomeSpecificError const &) 
    { 
    // specific error processing 
    } 
    catch(SomeOtherError const &) 
    { 
    // other error processing 
    } 

    ReportError(); 
} 

void ReportError() 
{ 
} 

15.1.4節告訴我們:

被拋出的 在未指定的方式分配給例外的臨時副本存儲,除了3.7.3.1中提到的情況外。只要有對 該異常正在執行的處理程序 暫時持續。特別是,如果處理程序通過執行 投擲而退出;語句,該控制權將控制權交給另一個處理程序,用於處理相同的異常,所以暫時保留。 當最後一個處理程序被 爲異常退出由不是拋出其他任何手段執行; 臨時對象被銷燬並且執行可能爲該臨時對象釋放內存 ;任何這樣的解除分配都是以未指定的方式在 中完成的。銷燬 破壞在 處理異常聲明中表示的對象之後立即發生。

我正確查看main中的處理程序是否爲「最後處理程序?」。因此在HandleException中允許任何數量的rethrow和catch都不會導致當前異常對象被破壞?

+4

¤'main'中的處理程序是最後一個,是的。是的,您可以根據需要多次重新拋出和重新排除異常。但是,這不是一個好主意。相反,讓您的處理程序執行(1)純粹的異常轉換,或者(2)純粹的日誌記錄和終止。這個處理程序代碼自然不具備處理失敗的知識。歡呼&hth。, – 2011-12-21 21:25:08

+0

@Alf謝謝。似乎我在發佈小代碼示例時省略了一些重要細節。實際上,ExceptionBase來自boost :: exception(從中提取許多常見的上下文數據)。此外,'main'實際上是任意數量的COM方法之一,因此在返回適當的HRESULT代碼之前記錄錯誤(包括常見和錯誤特定的上下文數據)。但無論如何,你已經回答了我的問題。 – 2011-12-21 21:56:22

回答

0

我正確地查看主處理程序中的「最後處理程序?」

是的,你是。

因此,在HandleException中允許任何數量的rethrow和catch都不會導致當前異常對象被破壞?

是的。最終未處理的異常對象將被編譯器生成的代碼銷燬。不會造成內存泄漏。

重投HandleException()不好。相反 1.將捕獲寫入任何請求特定處理的異常類型; 2.您可以使用dynamic_cast組的異常處理。捕獲基本異常類型並嘗試將其向下轉換爲其任何派生異常類。但是dynamic_cast不是很好的做法。所以最好使用第一種解決方案。

這是更好地重寫代碼的方式如下:

struct ExceptionBase : virtual std::exception{}; 
struct SomeSpecificError : virtual ExceptionBase{}; 
struct SomeOtherError : virtual ExceptionBase{}; 

void MightThrow(); 
void HandleExceptionBase(); 

int main() 
{ 
    try 
    { 
    MightThrow(); 
    } 
    catch (SomeOtherError &error) { 
    // first common code 
    HandleExceptionBase(); 
    // react on this exception correctly 
    // specific code 
    } 
    catch (SomeSpecificError &error) { 
    // first common code 
    HandleExceptionBase(); 
    // react on this exception correctly 
    // specific code 
    } 
    catch (ExceptionBase &error) { 
    HandleExceptionBase(); 
    // finally catch anything derived from base class 
    // react on this exception correctly 
    } 
    catch(...) { 
    // react on any other exception except 3 listed above 
    } 
} 

void MightThrow() 
{ 
    throw SomeSpecificError(); 
} 

void HandleExceptionBase() { 
    // base exception handler 
} 
+0

感謝您的回覆。但不幸的是,它並沒有回答我問過的問題。隨時編輯您的答案,我會很高興地upvote它。還要注意,你的代碼的行爲與原來的不同,因爲如果捕獲到'SomeOtherError'或'SomeSpecificError','ExceptionBase'的處理程序將不會被執行。 – 2011-12-28 01:28:24

0

感謝迄今發佈的評論和答案。我還沒有看到我正在尋找的東西,所以我要添加一些來自an answer provided by aschepler的信息到我的後續問題。

15.3p7:當catch子句的形式參數(如果有)完成初始化時,處理程序被認爲是活動的。 ...處理程序 不再被視爲積極當catch子句退出或當 的std ::意外(),由於被輸入到一個後拋退出。

15。3p8:最近激活的處理程序仍處於活動狀態的異常稱爲當前處理的異常。

我認爲標準的語言是很清楚這裏和main實際上是在最後處理程序。因此,異常的生命週期不受嵌套處理程序的影響。

相關問題