这是我的程序,只是为了找到pthread_exit和从线程返回的区别。
struct foo{
int a,b,c,d;
~foo(){cout<<"foo destructor called"<<endl;}
};
//struct foo foo={1,2,3,4};
void printfoo(const char *s, const struct foo *fp)
{
cout<<s;
cout<<"struct at 0x"<<(unsigned)fp<<endl;
cout<<"foo.a="<<fp->a<<endl;
cout<<"foo.b="<<fp->b<<endl;
cout<<"foo.c="<<fp->c<<endl;
cout<<"foo.d="<<fp->d<<endl;
}
void *thr_fn1(void *arg)
{
struct foo foo={1,2,3,4};
printfoo("thread1:\n",&foo);
pthread_exit((void *)&foo);
//return((void *)&foo);
}
int main(int argc, char *argv[])
{
int err;
pthread_t tid1,tid2;
struct foo *fp;
err=pthread_create(&tid1,NULL,thr_fn1,NULL);
if(err!=0)
cout<<"can't create thread 1"<<endl;
err=pthread_join(tid1,(void **)&fp);
if(err!=0)
cout<<"can't join with thread 1"<<endl;
exit(0);
}
在“* thr_fn1”线程函数中,我创建了一个对象foo。
根据网站pthread_exit vs. return 当我使用“return((void *)&amp; foo)退出线程函数”thr_fun1()“时;”它应该调用对象foo的析构函数,但是当我调用“pthread_exit((void *)&amp; foo)时,它不应该调用析构函数;”从函数“thr_fun1()”返回main。
但在两种情况下都使用“return((void *)&amp; foo);”或“pthread_exit((void *)&amp; foo);”调用函数“thr_fun1()”中的本地对象“foo”。
这不是我猜的行为。应该只在“return((void *)&amp; foo);”中调用析构函数。仅限案例。
如果我错了,请核实我?
答案 0 :(得分:4)
是的,没错。 pthread_exit()
立即退出当前线程,而不调用堆栈上方对象的任何析构函数。如果您使用C ++进行编码,则应确保始终从线程过程中return
,或者仅从最底层的堆栈帧中调用pthread_exit()
,而在该帧中没有具有析构函数的对象或任何更高的帧;否则,您将泄漏资源或导致其他不良问题。
答案 1 :(得分:4)
您的代码存在严重问题。具体来说,您使用局部变量作为pthread_exit()的退出值:
void *thr_fn1(void *arg)
{
struct foo foo={1,2,3,4};
printfoo("thread1:\n",&foo);
pthread_exit((void *)&foo);
//return((void *)&foo);
}
根据Pthreads spec,“线程终止后,线程的本地(自动)变量访问结果未定义。”
因此,从线程函数返回堆栈分配变量的地址作为线程退出值(在您的情况下为pthread_exit((void *)&foo)
)将导致任何检索并尝试取消引用该地址的代码出现问题。 / p>
答案 2 :(得分:2)
pthread_exit()
抛出异常,导致堆栈展开,并为本地调用析构函数。有关详细信息,请参阅https://stackoverflow.com/a/11452942/12711。
抛出的异常属于abi::__forced_unwind
类型(来自cxxabi.h
);互联网搜索可以为您提供更多详细信息。
注意:正如其他答案/评论所提到的那样,返回本地地址无论如何都不会起作用,但这就是问题的重点。如果返回某个其他有效地址(或空指针)而不是foo
,则会获得与销毁&foo
相同的行为。