0

据此_

“但是,如果线程调用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) 建立的尚未被弹出的清理处理程序,都会被弹出(与它们被推送的顺序相反)并执行。 如果线程有任何线程特定的数据,那么,在清理处理程序已被执行,相应的析构函数被调用,以未指定的顺序“。

这表示函数调用了析构函数,所以自动变量会被释放?那么为什么有必要使用代码所展示的异常处理呢?

4

2 回答 2

3

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

有关更多信息,请参见此处(以及 pthread 示例)。

于 2013-03-29T08:47:57.163 回答
1

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

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

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

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

于 2013-03-29T08:49:13.513 回答