簡體   English   中英

為什么這段代碼會阻塞不執行?

[英]Why does this code catch block not execute?

catch處理程序未運行。 但為什么?

如果thread ttry塊之前啟動,則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

你忘了加入主題:

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

超出范圍的可連接線程會導致terminate被調用 因此,您需要在超出范圍之前調用joindetach

C ++ 11,30.3.1.3中,標准說的是線程析構函數

如果joinable()然后terminate(),否則沒有效果。 [注意:隱式分離或連接其析構函數中的joinable()線程可能導致無法調試正確性(用於分離)或性能(用於連接)僅在引發異常時遇到的錯誤。 因此,程序員必須確保在線程仍可連接時永遠不會執行析構函數。 - 尾注]

因此,一旦調用了線程析構函數,程序就會terminate因為作用域結束並且永遠不會執行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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM