std::thread错误 terminate called without an active exception

std::thread错误 terminate called without an active exception

本人之前写过一篇文章介绍如何使用C++11的是线程库
C++11的新特性之线程类

问题

在之后的实践中发现一个问题,就是本文标题中列出的这个错误
terminate called without an active exception

本文中的代码使用下面的命令编译,编译环境 Centos 7,

$> g++ test.cpp -std=c++11 -ggdb -lpthread -o test

这个错误是在程序运行的时候出现的,编译阶段没有任何错误。问题代码如下,

“` c++
#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>

void task1(std::string msg){
std::cout << "task1 says: "<< msg;
}
int main() {
std::thread t1(task1, "hello");
return 0;
}

<pre><code><br>

本意是在主线程中创建一个线程答应一个字符串,但是程序没有任何输出,并且出错。原因就是std::thread在main()结束的时候,被销毁了。

除了上面这个这种情况,还有一种情况下(或者说使用场景)也会出现这个错误。这个问题是在子线程的对象是一个局部变量,在超出局部变量的生命周期,变量被销毁,下面的代码演绎了这种情况,

<br>
“`C++
#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
#include <unistd.h>

void task1(std::string msg){
std::cout << “task1 says: ” << msg;
}

void createThread( void )
{
try {
std::thread t1(task1, “hello”); }catch( … ){
std::cout<<“got exception”<<std::endl;
}
}

int main()
{
createThread();
while( true )
{
std::cout<<“main thread”<<std::endl;
usleep( 1000000 );
}

return 0;
}

解决办法

解决办法就是join或者detach

  • join方法

“` C++
#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>

void task1(std::string msg){
std::cout << "task1 says: " << msg;
}
int main() {
std::thread t1(task1, "hello");
t1.join();
return 0;
}

<pre><code><br />* detach方法

“` C++
#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>

void task1(std::string msg){
std::cout << “task1 says: ” << msg;
}

int main() {
std::thread t1(task1, “hello”);
t1.detach();
return 0;
}

注意这里,t1.detach()只是保证了,在运行的时候不报本文所讨论的错误,但是这样的做法在这个例子中是有问题的,因为子线程可能还有没有机会执行,主线程已经退出。所以上面的例子可以自行修改(因为这不是本文讨论的重点)。

原因

上面的程序会报上面的那个运行时的错误,然后进程退出,同时会生成core dump文件(如果你开启了生成core dump文件的开关),在linux下面开启生成core dump文件的开关的方法如下
$> ulimit -c unlimited

然后我们看看调用情况,
$> gdb test core.xxx
xxx是系统自动生成,根据你的系统生成的数字,自行修改。

(gdb) bt
#0  0x00007f9a72fe05f7 in raise () from /lib64/libc.so.6
#1  0x00007f9a72fe1ce8 in abort () from /lib64/libc.so.6
#2  0x00007f9a738e59d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
#3  0x00007f9a738e3946 in ?? () from /lib64/libstdc++.so.6
#4  0x00007f9a738e3973 in std::terminate() () from /lib64/libstdc++.so.6
#5  0x00000000004012ff in std::thread::~thread (this=0x7fff5c2a97f0, __in_chrg=) at /usr/include/c++/4.8.2/thread:143
#6  0x0000000000401196 in createThread () at test.cpp:13
#7  0x00000000004011a1 in main () at test.cpp:17

可以看到是因为对象被释放,调用析构函数,析构函数又调用terminate来结束线程,又调用了c++库函数,这个函数没有被打印出来,然后一个异常被抛出。

我们就线研究到这里,等日后有时间了,再研究为什么调用了terminate,就被抛出异常了,这部分就要看c++11库的实现代码了。

 

版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则
按侵权处理.

    分享到:

留言

你的邮箱是保密的 必填的信息用*表示