2015-06-16 16 views
7

Trình xử lý bắt không được chạy. Nhưng tại sao?Tại sao khối mã catch này không thực thi?

Nếu thread t được bắt đầu trước khối try, trình xử lý bắt sẽ chạy.

Nếu loại khối catch không khớp với loại được ném, chương trình thoát giải thích rằng luồng được kết thúc với một ngoại lệ chưa bắt buộc, cho thấy rằng ngoại lệ được xử lý, nhưng khối catch không chạy.

#include <iostream> 
#include <thread> 

using namespace std; 

void do_work() {} 

int main() { 
    std::cerr << "RUNNING" << std::endl; 
    try { 
    thread t(do_work); 
    std::cerr << "THROWING" << std::endl; 
    throw logic_error("something went wrong"); 
    } catch (logic_error e) { 
    std::cerr << "GOTCHA" << std::endl; 
    } 

    return 0; 
} 

Compile lệnh:

c++ -std=c++14 -pthread -pedantic -Wall -Wextra -O0 scratch.cpp -o scratch 
+2

vui lòng thụt lề mã của bạn trước khi nhấn nút gửi – bhavesh

+0

Tại sao điều này lại có một lưu ý? \ * scratches head \ * –

+0

@LightnessRacesinOrbit Một người nào đó có thể đã downvoted lại khi mã đã bị hỏng định dạng. – user2079303

Trả lời

5

Bạn quên tham gia các chủ đề:

try { 
    thread t(do_work); 
    t.join();         // <<< add this 
    std::cerr << "THROWING" << std::endl; 
    throw logic_error("something went wrong"); 
} catch (logic_error e) { 
    std::cerr << "GOTCHA" << std::endl; 
} 

Một joinable thread that goes out of scope, causes terminate to be called. Vì vậy, bạn cần gọi số join hoặc detach trước khi nó nằm ngoài phạm vi.

2

Trong C++ 11, 30.3.1.3, chủ đề destructor tiêu chuẩn nói

Nếu joinable() sau đó chấm dứt(), nếu không có e ff ECTS. [Lưu ý: Hoặc tách biệt hoặc tham gia một thread joinable() trong destructor của nó có thể dẫn đến việc sửa lỗi chính xác (cho tách) hoặc hiệu suất (để tham gia) chỉ xảy ra khi ngoại lệ được nâng lên. Do đó, lập trình viên phải đảm bảo rằng destructor không bao giờ được thực hiện trong khi luồng vẫn có thể nối được. —end note]

Do đó, chương trình của bạn được gọi là vì phạm vi kết thúc được gọi vì phạm vi kết thúc và logic catch không bao giờ được thực hiện.

Nếu bạn muốn chương trình của bạn bắt ngoại lệ trong phạm vi của chủ đề nhưng ném trong khi chuỗi vẫn có thể nối, bạn sẽ cần phải nắm bắt nó trong phạm vi của chủ đề, join hoặc detach chuỗi và làm lại mọi thứ đã bị bắt.

try 
{ 
    std::thread t(foo); 
    try 
    { 
    std::cerr << "THROWING" << std::endl; 
    throw std::logic_error("something went wrong"); 
    } 
    catch (...) // catch everything 
    { 
    t.join(); // join thread 
    throw; // rethrow 
    } 
    t.join(); 
} 
catch (std::logic_error & e) 
{ 
    std::cerr << "GOTCHA: " << e.what() << std::endl; 
} 
Các vấn đề liên quan