我有一个使用文件描述符的线程,取消时必须close()
文件描述符。伪代码看起来像:
static void thread_cleanup(void *args)
{
int *fd = (int *)args;
close(*fd);
}
void *thread(void *arg)
{
int fd = open(...);
...
pthread_cleanup_push(thread_cleanup, &fd);
....
}
我选择的一个选项是将fd
从void *
投放到thread
,然后让thread_cleanup
将其投放回int
,但这样做如果sizeof(int) != sizeof(void *)
可能会导致问题。我的问题是:以这种方式使用时,是否像伪代码安全一样传递堆栈变量?
答案 0 :(得分:1)
您对sizeof
的担忧似乎是基于一些混乱。 int
和void *
之间没有转换,因此无论它们是相同的大小,还是一个的值都可以在另一个中表示,都是无关紧要的。发生的事情是,fd
的地址(类型为int *
的指针值)正在转换为void *
并返回int *
。这是void *
的重点,非常正确。
至于指向对象是否“在堆栈上”(在推送/弹出清除处理程序的函数中具有自动存储持续时间的对象)是否重要,答案是肯定的,但您的使用是可以的
形式上(正如POSIX中的当前规范所写),任何其生存期未在取消之前结束的对象仍然存在,并且可以从所有清理处理程序访问。但是,这似乎是标准中的错误,因为它与支持基于展开的实现(如大多数实际实现)的Rationale文档冲突,其中取消清理处理程序在它们被推送的块上下文中执行。由于函数int fd;
中的对象thread
具有与pthread_cleanup_push
块之外的包含块关联的生命周期,因此从清理处理程序thread_cleanup
访问它是完全安全的。