关于pthread_exit释放自动变量的困惑

时间:2013-03-29 08:45:02

标签: c++ pthreads

根据this

“如果线程调用pthread_exit,C ++不保证析构函数 调用线程堆栈上的所有自动变量。一种聪明的方法来恢复这个 功能是在线程函数的顶层调用pthread_exit 抛出一个特殊的例外“。

随后是随附的代码

class ThreadExitException
{

public:
ThreadExitException (void* return_value)
                    : thread_return_value_ (return_value) { }

void* DoThreadExit ()
{
 pthread_exit (thread_return_value_);
}

private:
void* thread_return_value_;

};

void do_some_work ()
{
while (1) 
{
 /* Do some useful things here...*/
 if (should_exit_thread_immediately ())
 throw ThreadExitException (/* thread’s return value = */ NULL);
}
}

void* thread_function (void*)
{
 try 
 {
  do_some_work ();
 }
catch (ThreadExitException ex) 
{
 ex.DoThreadExit ();
}

return NULL;
}

据我所知...... 如果调用pthread_exit,则可能无法调用堆栈的所有自动变量的析构函数。 因此我们使用异常处理来确保为所有变量调用析构函数。 (引自解释:“通过抛出ThreadExitException而不是 直接调用pthread_exit,异常被捕获在顶级线程函数中,线程堆栈上的所有局部变量都将被正确销毁,因为 异常渗透。“

根据pthread_exit

的手册页

“由pthread_cleanup_push(3)建立的任何尚未弹出的清理处理程序将被弹出(与它们被按下的顺序相反)并且       执行。 如果线程有任何特定于线程的数据,那么在执行清理处理程序之后,将调用相应的析构函数,        未指定的订单“。

这表示destructrutors被调用函数,因此自动变量将被释放?那么为什么有必要使用代码所示的异常处理?

2 个答案:

答案 0 :(得分:3)

线程特定数据与您理解的内容不同。线程特定数据是已设置的全局数据,以便每个线程获得全局数据的单独副本。因此,线程特定数据不会像您假设的那样存在于堆栈中。

有关详情,请参阅here(以及pthread示例)。

答案 1 :(得分:1)

不,它表示会为特定于线程的数据调用析构函数。这与在线程调用堆栈中调用自动变量的C ++析构函数完全不同。

有关与特定于线程的数据相关的析构函数的文档,请参阅man pthread_key_create

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
  

[...]可选的析构函数可以与每个键值相关联。在线程退出时,如果键值具有非NULL析构函数指针,并且该线程具有与该键关联的非NULL值,则该键的值将设置为NULL,然后使用该键调用指向的函数先前关联的值作为其唯一参数。如果线程退出时存在多个析构函数,则不指定析构函数调用的顺序。 [...]