2015-06-01 62 views
5

如果我在std::exception_ptr內存儲了異常。我使用std::rethrow_exception重新拋出異常,使用catch(MyException&)訪問它,然後修改該值。我可以修改std :: exception_ptr中的異常值嗎?

如果我再次拋出同樣的異常,我應該觀察我所做的修改嗎?

下面的代碼演示了我的想法:

#include <exception> 
#include <iostream> 

struct MyException { 
    int value; 
}; 

int main() { 
    std::exception_ptr a = std::make_exception_ptr(MyException()); 

    try { 
     std::rethrow_exception(a); 
    } catch(MyException& b) { 
     std::cout << b.value << std::endl; 
     b.value = 3; 
    } 

    try { 
     std::rethrow_exception(a); 
    } catch(MyException& b) { 
     std::cout << b.value << std::endl; 
    } 
} 
+0

觀察修改意味着什麼? – perencia

+0

@perencia如果我重新拋出同樣的異常,它會進行修改。在我的代碼示例中,我第二次拋出'a',在'value'中有3個。 –

+0

在這個例子中,你總是使用同一個對象,通過引用來捕獲它。 – perencia

回答

6

您的代碼一致,便於攜帶。在這裏,但有怪物:

  • 如果您獲得您exception_ptr通過current_exception(),它是否得到當前異常的副本,或者當前異常本身的基準的基準是不確定的。即使您連續調用current_exception()兩次,您也可能會獲得對同一個異常對象的引用。

  • 由於exception_ptr是可複製,並複製可以指向同一個異常對象,並rethrow_exception不進行復印,它很可能兩個線程同時拋出同樣的異常對象。因此,在多線程程序中,要知道在catch子句中是否有唯一的異常訪問異常可能非常困難。對該異常的修改可能會導致數據競爭。數據競賽可能存在於某些平臺上,而不是其他平臺上,具體取決於current_exception()是否生成副本。

所以,如果你必須在多線程程序修改異常對象,它是最安全的第一個複製,修改副本,然後重新拋出的副本(如有必要)。

UPDATE

對不起,我已經給了一個不正確的答案。

使用:http://webcompiler.cloudapp.net的示例代碼的輸出是:

0 
0 

的VS落實rethrow_exception似乎使異常的副本。

Clang和gcc不會複製副本。

+0

那麼在rethrow異常上不能有副本? – Yakk

+1

@Yakk:這就是我讀[傳播]/p10的方式:*拋出:* p引用的異常對象。相反,描述'current_exception()'的p8在描述未指定的複製語義方面做了很多工作。 –

+0

根據你的回答,我可以推斷回答http://stackoverflow.com/questions/30462906/is-it-safe-to-use-an-exception-outside-the-catch-statement-if-it-是否持有「是的,這是安全的」? –

相關問題