Исключение не перехватывается, если возникает после порождения 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
быть вызванным таким образом, обработчик исключений никогда не вызывается.
Кроме того, запись в стандартные потоки из разных потоков без надлежащей синхронизации не очень хорошая идея.
Хорошо, после некоторых исследований я нашел решение этой проблемы. Нужно обернуть поток в класс и создать его экземпляр вместо создания необработанного потока. В деструкторе можно проверить, является ли поток все еще присоединяемым, и выполнить действия, чтобы по возможности корректно остановить тело потока. В таком случае, когда выдается исключение, деструктор будет вызван, пока поток еще работает, и он разберется с вещами.