2012-10-27 54 views
11

http://en.cppreference.com/w/cpp/error/terminate中所述,有很多原因要求終止。我可以想象這種情況,幾乎在同一時間其中一些原因發生在兩個線程中。用戶必須提供terminate()函數是否線程安全?

Q1可以同時調用std::set_terminate設置的終止函數兩次或更多,同時我的意思是第二次調用在第一次調用結束之前開始。

Thread1 Thread2 
    |   | 
    _   | 
    t   | 
    e   | 
    r   | 
    m   | 
    i   _ 
    n   t 
    a   e 
    t   r 
    e   m 
    -   ? 

Q2如果Q1 == YES,那麼會發生什麼,如果第一終止結束。我猜如果它以std :: abort結束,程序結束,但如果用戶提供的終止不會中止程序會發生什麼?

Q3是對終止函數由std::set_terminate設置導致了這一終止調用線程的上下文中調用?

回答

7

Q1

是,std::terminate可以同時調用。

Q2

標準說,這是不確定的行爲的terminate_handler不「而不返回給調用終止程序的執行。」在我熟悉的實現中,如果terminate_handler嘗試返回,通常或異常地調用abort()

Q3

通過std::terminate設置的功能是一個全球性的,而不是一個本地線程。所以一個線程會影響另一個線程

在C++ 98/03,當terminate被稱爲使用,因爲未捕獲到異常的terminate_handler是一個時有效拋出異常,而不是一個有效時terminate實際上是所謂的(雖然他們通常是相同的)。

在C++ 11中,這被改變了,標準現在說所使用的處理程序是在調用terminate的時候使用的處理程序。這種改變是錯誤的,很可能在未來的草案中得到糾正。這裏是LWG問題追蹤這個問題:

http://cplusplus.github.com/LWG/lwg-active.html#2111

更新

在列涅薩,KS在2015年春季會議上,LWG決定來規範現有的行爲,並使其未指定當一個新的terminate_handler如果在堆棧展開期間調用set_terminate,則生效。即實現被允許遵循C++ 98/03規則或C++ 11規則。

爲使您的代碼具有可移植性,如果您需要設置terminate_handler,請在程序啓動過程中,在拋出任何異常之前執行此操作,並且在此之後不要習慣於調用set_terminate

+0

+1。只是在主題回答問題:用戶提供的終止函數必須是線程安全的?其他的「災難」功能呢?那麼new_handler呢?這是海灣合作委員會的建議危險的雙重刪除:http://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html? – PiotrNycz

+0

既然'std :: terminate'可以同時調用,'terminate_handler'應該是線程安全的。標準中指定的所有其他處理程序也是如此,包括'new_handler'。是的,gcc示例有可能執行雙重刪除。這可以通過「安全」原子交換來解決。 –

+0

「由std :: set_terminate設置的函數是全局的」 - 爲什麼?某些實現表示它是本地的([ms:終止函數針對每個線程分別維護](http://msdn.microsoft.com/en-us/library/aa272914(v = vs.60).aspx); [ibm :您可以使用線程級終止來覆蓋此選項](http://publib.boulder.ibm.com/infocenter/zos/v1r11/index.jsp?topic=/com.ibm.zos.r11.bpxbd00/setterm。 htm); [sun:線程可以自己設置](http://www.amath.unc.edu/sysadmin/DOC4.0/c-plusplus/c%2B%2B_ug/Exception_Handling.doc.html))Can' t在standard.http://stackoverflow.com/q/15367060/196561中找到確切的定義 – osgx