2012-10-27 26 views
11

Như đã nêu trong http://en.cppreference.com/w/cpp/error/terminate có nhiều lý do để gọi chấm dứt. Tôi có thể tưởng tượng trường hợp mà chỉ gần như trong cùng một thời gian một số trong những lý do này xảy ra trong hai chủ đề.Người dùng phải cung cấp chức năng chấm dứt() có an toàn không?

Q1 Chức năng chấm dứt được đặt bởi std::set_terminate được gọi hai lần trở lên cùng một lúc, đồng thời tôi có nghĩa là cuộc gọi thứ hai bắt đầu trước khi kết thúc lần đầu tiên.

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

Q2 Nếu Q1 == YES, sau đó điều gì sẽ xảy ra nếu đầu tiên chấm dứt kết thúc. Tôi đoán nếu nó đã kết thúc với std :: hủy bỏ, sau đó chương trình kết thúc, nhưng những gì sẽ xảy ra nếu người dùng cung cấp chấm dứt không hủy bỏ chương trình?

Q3 Chức năng chấm dứt được đặt bởi std::set_terminate có được gọi trong ngữ cảnh của chuỗi gây ra cuộc gọi kết thúc này không?

Trả lời

7

Q1

Vâng, std::terminate có thể được gọi đồng thời.

Q2

Các tiêu chuẩn nói đó là hành vi không xác định cho một terminate_handler để không "chấm dứt thực hiện chương trình mà không phải quay người gọi". Trong các triển khai tôi đã quen thuộc, nếu số lần trả lại terminate_handler, bình thường hoặc đặc biệt, abort() sẽ được gọi.

Q3

Chức năng thiết lập bởi std::terminate là một toàn cầu, không phải là một chủ đề của địa phương. Vì vậy, một chủ đề có thể tác động đến một chủ đề khác.

Trong C++ 98/03, các terminate_handler sử dụng khi terminate được gọi là do một ngoại lệ còn tự do là một trong đó đã có hiệu lực khi các ngoại lệ được ném ra, không phải là người có hiệu lực khi terminate là thực sự gọi (mặc dù họ thường giống nhau).

Trong C++ 11 điều này đã được thay đổi và bây giờ tiêu chuẩn nói rằng trình xử lý được sử dụng là một tại chỗ tại thời điểm terminate được gọi. Thay đổi này được thực hiện do nhầm lẫn và rất có thể sẽ được sửa chữa trong bản nháp trong tương lai. Đây là vấn đề LWG theo dõi vấn đề này:

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

Cập nhật

Tại cuộc họp mùa xuân năm 2015 Lenexa, KS, các LWG quyết định chuẩn hành vi hiện tại và làm cho nó không xác định khi một mới terminate_handler có hiệu lực nếu set_terminate được gọi trong quá trình thư giãn. I E. triển khai được phép tuân theo các quy tắc C++ 98/03 hoặc các quy tắc C++ 11.

Để làm cho mã của bạn di động, nếu bạn cần đặt terminate_handler, hãy làm như vậy trong khi khởi động chương trình, trước khi có bất kỳ ngoại lệ nào và không thực hiện thói quen gọi set_terminate sau đó.

+0

+1.Chỉ để trả lời câu hỏi trong chủ đề: người dùng cung cấp chức năng chấm dứt phải là chủ đề an toàn? Còn về các chức năng "thiên tai" khác? Thế còn new_handler thì sao? Lời khuyên về gcc này có nguy hiểm không bị xóa kép: http://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html? – PiotrNycz

+0

Vì 'std :: terminate' có thể được gọi đồng thời,' terminate_handler' nên là luồng an toàn. Và điều này cũng đúng với tất cả các trình xử lý khác được chỉ định trong tiêu chuẩn, bao gồm 'new_handler'. Có, ví dụ về gcc có nguy cơ thực hiện thao tác xóa kép. Điều này có thể được giải quyết với một trao đổi nguyên tử về 'an toàn'. –

+0

"chức năng thiết lập bởi std :: set_terminate là một toàn cầu" - Tại sao? Một số triển khai nói rằng nó là cục bộ ([ms: các hàm kết thúc được duy trì riêng cho mỗi luồng] (http://msdn.microsoft.com/en-us/library/aa272914 (v = vs.60) .aspx); [ibm : Bạn thể ghi đè lên điều này với một chấm dứt chủ đề cấp] (http://publib.boulder.ibm.com/infocenter/zos/v1r11/index.jsp?topic=/com.ibm.zos.r11.bpxbd00/setterm. htm); [sun: thread có thể tự thiết lập] (http://www.amath.unc.edu/sysadmin/DOC4.0/c-plusplus/c%2B%2B_ug/Exception_Handling.doc.html)) Can ' t tìm định nghĩa chính xác trong tiêu chuẩn.http: //stackoverflow.com/q/15367060/196561 – osgx

Các vấn đề liên quan