2014-05-23 165 views
2

我有一個C++程序通過setrlimit強加內存限制。根據參數,它可能會在我想要處理的各個位置上拋出std :: bad_alloc。無法捕獲由std :: thread構造函數拋出的異常

我使用多個線程通過std :: thread。我有一些代碼沿着這條線:

std::thread* worker; 
try 
{ 
    worker=new std::thread[NUM_THREADS]; 
    for(int i=0;i<NUM_THREADS;++i) 
    { 
     worker[i]=std::thread(&ThisClass::SomeMemberFunc, this, SomeArg...); 
    } 
} 
catch(...) 
{ 
    std::cout << "exception in thread creation" << std::endl; 
} 

所以線程創建包裹在try/catch中。然而,它發生,該方案與中止:

terminate called after throwing an instance of 'St9bad_alloc' 
what(): std::bad_alloc 

當我使用GDB和中止(設置斷點),回溯看起來像:

#0 __GI_abort() at abort.c:53 
#1 0x00007ffff717269d in __gnu_cxx::__verbose_terminate_handler()() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#2 0x00007ffff7170846 in ??() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#3 0x00007ffff7170873 in std::terminate()() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#4 0x00007ffff7127cfb in ??() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#5 0x00007ffff73c2e9a in start_thread (arg=0x7ffff3e86700) at pthread_create.c:308 
#6 0x00007ffff6bd93fd in clone() at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 
#7 0x0000000000000000 in ??() 

現在,這怎麼可能?

+0

如果寫入'cout'會拋出什麼? –

+1

我看起來好像在新創建的線程中從'SomeMemberFunc'拋出異常,而不是從線程構造函數本身拋出異常。你可以將'SomeMemberFunc'的主體包裝到try-catch塊嗎? – nosid

+3

不是答案,而是使用'std :: vector '而不是'std :: thread *'。 – Chnossos

回答

1

事實上,它是拋出異常的SomeMemberFunc

nosid建議使用std::async而不是std::thread來捕獲呼叫方的異常。

我決定將SomeMemberFunc拋出的異常通過std::current_exception()存儲在std::exception_ptr中。加入線程後,我檢查異常指針。

0

線程不會捕捉對方的例外。沒有「父」線程的概念,因爲在「子」線程中拋出異常時,這種線程可能不再存在。

如果您需要線程通過異常,您需要自己實現它,方法是將SomeMemberFunc包裝到try-catch塊中,並將捕獲到的異常複製到「父」線程的變量中,以後重新執行。請注意,當其他線程正在運行時,您需要阻止調用線程(「父」),以強制執行層次結構(線程本身可以重複使用以並行調用SomeMemberFunc之一,因此您不會浪費完全線程)。

相關問題