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库的实现代码了。
版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则
按侵权处理.