[英]Throwing bad_exception when calling current_exception()
鏈接https://en.cppreference.com/w/cpp/error/current_exception提供了current_exception()
的以下描述:
如果在異常處理期間調用(通常在 catch 子句中),則捕獲當前異常 object 並創建一個 std::exception_ptr 來保存對該異常 object 的副本或引用(取決於實現)。
...
如果此 function 的實現需要復制捕獲的異常 object 並且其復制構造函數拋出異常,則返回的指針將持有對拋出異常的引用。 如果拋出的異常 object 的復制構造函數也拋出,則返回的指針可能持有對 std::bad_exception 實例的引用以中斷無限循環。
我試圖找出 GCC7 中current_exception()
的實現是否復制了捕獲的異常 object,或者只是返回對已經存在的 object 的引用。 到目前為止,我認為 GCC 實現了第二種情況。 我試圖通過執行以下代碼來檢查它:
class my_copy_exception : public exception
{
public:
my_copy_exception () : exception () {}
my_copy_exception (const my_copy_exception& other) :
exception(other)
{
throw my_copy_exception();
}
const char* what () const throw() {return "my_copy_exception";}
};
int main()
{
try
{
throw my_copy_exception();
}
catch (const exception& e)
{
cout << e.what() << endl;
exception_ptr eptr = current_exception();
try
{
rethrow_exception(eptr);
}
catch(const std::exception& en)
{
cout << en.what() << endl;
exception_ptr eptrn = current_exception();
cout << (eptr == eptrn) << endl;
}
}
}
它產生以下 output:
my_copy_exception
my_copy_exception
1
是否可以聲稱沒有異常object的復制? 如果沒有,如何讓current_exception()
拋出bad_exception
?
像 GCC 7 這樣的開源軟件的好處在於,與其嘗試對它可能正在做的事情進行逆向工程,您可以簡單地 go 並查看源代碼以確切了解它在做什么。
在 GCC 7.4 的情況下,可以在 libstdc++ 中找到std::current_exception()
的實現,更具體地說,在libsupc++/eh_ptr.cc 第 177 行中:
std::exception_ptr
std::current_exception() noexcept
{
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
if (!header)
return std::exception_ptr();
// Since foreign exceptions can't be counted, we can't return them.
if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
return std::exception_ptr();
return std::exception_ptr(
__get_object_from_ambiguous_exception (header));
}
這里的前幾行只是獲取當前活動的異常。 如果沒有活動異常或活動異常不是來自此 C++ 運行時,則返回一個空的exception_ptr
(有關這些檢查如何操作的詳細信息,請參見此處、 此處、 此處、 此處、 此處、 此處和此處)。 如果存在確實來自 C++ 運行時的活動異常, 則它會為自己獲取一個指向活動異常 object 的指針並構造一個exception_ptr
。 它使用的exception_ptr
構造函數只是增加異常 object 的引用計數器。
因此,似乎 libstdc++ 異常是引用計數的,並且從未在 GCC 7 的std::current_exception()
的 libstdc++ 實現中制作副本,這符合規范的要求,並且似乎符合您的觀察結果……
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.