Почему этот блок catch кода не выполняется?

обработчик catch не выполняется. Но почему?

если thread t начато до try блок, обработчик catch работает.

если тип блока catch не соответствует типу брошенного, программа завершает работу, объясняя, что поток завершен с необработанным исключением, предполагая, что исключение обрабатывается, но блок catch не запускается.

#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;
}

команды компиляции:

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

2 ответов


вы забыли присоединиться к потоку:

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;
}

A присоединяемый поток, который выходит за рамки, вызывает terminate называли. Итак, вам нужно позвонить либо join или detach прежде чем он выйдет за рамки.


на в C++11, 30.3.1.3, деструктор потока стандарт говорит

Если joinable (), то завершите (), иначе никаких эффектов. [Примечание: неявное отсоединение или присоединение к потоку joinable() в его деструкторе может привести к трудным для отладки ошибкам корректности (для отсоединения) или производительности (для соединения), возникающим только при возникновении исключения. Таким образом, программист должен убедиться, что деструктор никогда не выполняется, пока поток все еще соединяется. -конец Примечание]

программа terminateS как только деструктор потока вызывается, потому что область заканчивается и catch логика никогда не выполняется.

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

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;
}