2012-08-06 75 views
0

我有一段網絡代碼引發各種異常,這些異常都被捕獲到一般的catch異常聲明。處理特定的異常

try { 
    network code 
} catch (Exception e) { 
    freeaddrinfo(some_address); 
} 

此方法的問題是異常中的freeaddrinfo。並非所有的例外情況都可以/應該調用freeaddrinfo,在我的具體情況下,當有一個無效的地址被傳遞到網絡代碼連接到某個地方時,不應該調用freeaddrinfo。我的解決這個問題的想法是檢索由此異常拋出的錯誤代碼,並可能將此與e.to_string結合使用來處理此邊界情況。從我從Effective Java學到的知識,這是處理這個問題的一種脆弱的方式。你應該怎麼做?

+0

我認爲問題標籤是錯誤的。 – hmjd 2012-08-06 15:00:07

+0

你推薦什麼標籤? – 2012-08-06 15:00:31

+4

扔掉Java書並學習C++?這是一種完全不同的語言...... – 2012-08-06 15:00:36

回答

2

在C++中,通常的方式釋放資源後的異常是不捕獲異常,但包裹在資源的對象,其析構函數負責釋放。這樣,當管理對象超出範圍(或以其他方式被銷燬)時它被釋放,無論是否拋出異常。這種技術被稱爲RAII

A(非常基本的)管理對象可能看起來像:

struct AddressInfo { 
    addrinfo * info; 

    // Constructor takes ownership of resource 
    explicit AddressInfo(addrinfo * info) : info(info) {} 

    // Destructor releases resource 
    ~AddressInfo() {freeaddrinfo(info);} 

    // Prevent shallow copying, so only one object manages the resource 
    AddressInfo(AddressInfo const &) = delete; 
    void operator=(AddressInfo const &) = delete; 
}; 

那麼你的代碼將變成:

// some network code 
AddressInfo address(some_address); 
// some more network code 

,無需任何異常處理或手動清理代碼。

+0

我對RAII的問題是,當我在一個已經分配給addrinfo結構的無效地址上調用freeaddrinfo時,在清理期間我將拋出一個異常,因爲freeaddrinfo會因爲無效地址而失敗。 – 2012-08-06 15:25:46

+2

@JasonZhu:所以不要創建管理對象(或者可能創建它,但將其指針設置爲空,並在析構函數中檢查它),直到獲得有效地址。 – 2012-08-06 15:27:13

1

如果你堅持使用異常,那麼網絡代碼應該根據錯誤的性質提出一個非常特殊的異常(類型)。也就是說,網絡代碼應該引發一個例外,就其性質而言,意味着是否可以調用freeaddrinfo()

+0

因此,創建一個新的異常類型,拋出新的異常類型,並抓住它呢? – 2012-08-06 15:03:06

+2

@JasonZhu正確。可能有多種異常類型;少數這些異常類型的特定處理程序將調用'freeaddrinfo()'。 – chrisaycock 2012-08-06 15:04:16

0

創建更具體的異常並拋出它們?然後,你可以先抓住那些人,然後再回到普通的捕獲物上。

try { 
network code 
} 
catch (SomeException1 e) { freeaddrinfo(some_address); } 
catch (SomeException2 e) { freeaddrinfo(some_address); } 
catch (Exception e) { }