Исключение не перехватывается, если возникает после порождения std::thread

Я озадачен странным поведением исключений, которые генерируются в главном потоке после порождения другого потока:

void thread_body(){
    while(true) cout << "in thread" << endl;
}

int main(int argc, char** argv)
{
    try{
        auto t = std::thread( thread_body );

        throw std::runtime_error("error!");

        t.join();
    } catch (const std::exception& e) {
        cout << e.what() << endl;
    }
}

Выход:

in thread
in thread
in thread
terminate called without an active exception
The program has unexpectedly finished.

Если я брошу, прежде чем порождать поток, как это:

throw std::runtime_error("error!");
auto t = std::thread( thread_body );

чем ловится нормально:

ошибка!

Почему исключение не пойман в первом случае? Что я должен сделать, чтобы поймать это обычным способом?

2 ответа

Решение

При возникновении исключения объект потока будет уничтожен. Но деструктор потока будет вызван, пока он все еще присоединяемый. Это вызывает terminate быть вызванным таким образом, обработчик исключений никогда не вызывается.

Кроме того, запись в стандартные потоки из разных потоков без надлежащей синхронизации не очень хорошая идея.

Хорошо, после некоторых исследований я нашел решение этой проблемы. Нужно обернуть поток в класс и создать его экземпляр вместо создания необработанного потока. В деструкторе можно проверить, является ли поток все еще присоединяемым, и выполнить действия, чтобы по возможности корректно остановить тело потока. В таком случае, когда выдается исключение, деструктор будет вызван, пока поток еще работает, и он разберется с вещами.

Другие вопросы по тегам