【问题标题】:Unable to catch exception thrown by std::thread constructor无法捕获 std::thread 构造函数抛出的异常
【发布时间】:2014-05-23 17:44:08
【问题描述】:

我有一个通过 setrlimit 施加内存限制的 C++ 程序。根据参数,它可能会在我想要处理的不同位置抛出 std::bad_alloc。

我通过 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 并在 abort() 处设置断点时,回溯如下所示:

#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 ?? ()

现在,这怎么可能?

【问题讨论】:

  • 如果写信给cout 抛出异常怎么办?
  • 我看起来好像异常是从新创建的线程中的SomeMemberFunc 引发的,而不是从线程构造函数本身引发的。你能把SomeMemberFunc 的主体包裹到一个try-catch 块中吗?
  • 不是答案,而是使用std::vector&lt;std::thread&gt; 而不是std::thread *
  • 感谢艾伦和诺西德。实际上是 SomeMemberFunc 抛出了。我已经怀疑过这一点,并且有一个函数 try/catch 围绕它。但我完全错过了事实上我在 catch 块中处理的一部分可能会再次抛出。我八小时都无法回答自己……
  • 您可以尝试使用std::async(std::launch::async, ...) 而不是std::thread。使用前者,您也可以在调用端捕获异常。

标签: c++ multithreading exception


【解决方案1】:

线程不会捕获彼此的异常。没有“父”线程的概念,因为在“子”线程中引发异常时,这样的线程甚至可能不再存在。

如果您需要线程传递异常,您需要自己实现它,方法是将SomeMemberFunc 包装在 try-catch 块中,并将捕获的异常复制到“父”线程的变量中,稍后在该变量中重新抛出.请注意,您需要在其他线程正在运行时阻塞调用线程(“父”),以强制执行层次结构(线程本身可以被重用以并行调用 SomeMemberFunc 之一,所以你不要完全浪费一个线程)。

【讨论】:

    【解决方案2】:

    实际上是SomeMemberFunc 引发了异常。

    nosid 建议使用std::async 而不是std::thread 来捕获调用端的异常。

    我决定通过std::current_exception()SomeMemberFunc 抛出的异常存储在std::exception_ptr 中。加入线程后,查看异常指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-14
      • 2011-11-04
      • 1970-01-01
      • 1970-01-01
      • 2013-01-20
      • 1970-01-01
      相关资源
      最近更新 更多