2012-04-02 91 views
2

當我使用boost::copy_exception將例外複製到exception_ptr時,我丟失了類型信息。看看下面的代碼:爲什麼使用boost :: copy_exception時會丟失類型信息?

try { 
    throw std::runtime_error("something"); 
} catch (exception& e) { 
    ptr = boost::copy_exception(e); 
} 
if (ptr) { 
    try { 
     boost::rethrow_exception(ptr); 
    } catch (std::exception& e) { 
     cout << e.what() << endl; 
     cout << boost::diagnostic_information(e) << endl; 
    } 
} 

由此,我得到下面的輸出:

N5boost16exception_detail10clone_implISt9exceptionEE 
Dynamic exception type: boost::exception_detail::clone_impl<std::exception> 
std::exception::what: N5boost16exception_detail10clone_implISt9exceptionEE 

所以基本上boost::copy_exception靜態複製它得到了論證。

如果我用boost::enable_current_exception來代替這個問題,這個問題就解決了。

try { 
    throw boost::enable_current_exception(std::runtime_error("something")); 
} catch (...) { 
    ptr = boost::current_exception(); 
} 
if (ptr) { 
    try { 
     boost::rethrow_exception(ptr); 
    } catch (std::exception& e) { 
     cout << e.what() << endl; 
     cout << boost::diagnostic_information(e) << endl; 
    } 
} 

問題在於,有時例外情況是由不使用boost::enable_current_exception的庫引發的。在這種情況下,除了逐一捕捉每種可能的例外情況並在每一種情況下使用boost::copy_exception之外,是否有任何方法可將異常置入exception_ptr

+0

我不是很熟悉boost異常,但是你在'catch'塊中嘗試了一個簡單的'throw;',它在拋出當前異常的同時又保留了它的類型嗎? – Asha 2012-04-02 09:04:03

+0

你可能正在遭受[切片](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c)問題。 – enobayram 2012-04-02 09:07:57

回答

4

這是設計,你的分析是正確的:使用靜態類型,而不是動態類型。實際上,爲了避免這種意外,在導致C++ 11的過程中,boost::copy_exception變成了std::make_exception_ptr。這樣,current_exception(無論Boost版本還是C++ 11版本)是正確的事情,正確地捕獲當前的異常。在代碼中使用啓用Boost.Exception的異常時,強烈建議使用BOOST_THROW_EXCEPTION或至少boost::throw_exception

對於第三方代碼,除了您已經提到的代碼或其他一些道德等價物(如dynamic_cast-對構成異常類型層次結構或層次結構的不同葉子類,或者typeid濫用)。

在這方面,異常處理與使用一個或多個多態類型的層次結構相同,並且您在此嘗試的操作是虛擬副本,也稱爲克隆:您的代碼可能被設計爲侵入式支持(如使用例如BOOST_THROW_EXCEPTION(e);而不是throw e;),或者你會痛苦地走繼承樹。請注意,您至少可以將這種痛苦重構爲只有一個網站,這樣您最終可以

try { 
    third_party_api(); 
} catch(...) { 
    ptr = catch_exceptions_from_api(); 
} 
相關問題