簡體   English   中英

調用 current_exception() 時拋出 bad_exception

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM