1

我尝试使用这样的 void 函数创建 POSIX 线程:

void thread_func(void* p_Arg)
{
    printf("Hello, World!\n");
}

int main(void)
{
    pthread_t thread;
    pthread_create(&thread, NULL, (void*)thread_func, (void*)NULL);

    return 0;
}

代码工作正常!但是在这种情况下将 thread_func 转换为 void* 是否安全?

4

3 回答 3

3

不,您的代码将在 IA64 上崩溃。函数指针转换是一个等待发生的错误。只需使用正确的签名并返回一个像 0 这样的虚拟值。

另请注意,将函数指针 (like void (*)(void*)) 转换为对象指针 (like void*) 也是一种潜在的不安全操作,因为 C 标准不保证对象指针和函数指针具有相同的表示形式。我不知道任何使用不同表示的即时架构,但函数指针当然有可能包含通常不存在于对象指针中的额外上下文位。

因此,除非您使用明确允许的实现,否则您永远不应该将函数指针转换为对象指针——例如,POSIX 系统需要这样做dlsym(3),因此可以安全地将 from的返回值从对象指针转换为函数指针.

于 2012-08-16T17:31:34.310 回答
2

在这种情况下将 thread_func 转换为 void* 是否安全

这可能适用于许多平台,但您应该知道:

  • Avoid *只保证能够存储对象指针而不是函数指针
  • 您的线程函数应该返回void *,并且没有完全合法的方法。例如,我想知道当您pthread_join使用非 NULL 结果时会发生什么

指向 void 的指针可以转换为指向任何对象类型的指针或从指向任何对象类型的指针转​​换。指向任何对象类型的指针都可以转换为指向 void 的指针并再次返回;结果应与原始指针比较。

而且当然:

指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果应与原始指针比较。如果转换后的指针用于调用类型与引用类型不兼容的函数,则行为未定义。

于 2012-08-16T17:31:31.737 回答
0

虽然 C 编译器在隐式执行危险的指针转换时传统上更宽容(比 C++ 编译器),但我发现很难相信任何 C 编译器都会允许您void *为函数指针参数提供参数而不生成大量诊断消息。你有没有忘记包含pthread.h,从而迫使 C99 之前的编译器推断参数类型而不是依赖函数原型pthread_create

在任何情况下,如果你真的想依赖这个 hack,至少将指针转换为正确的目标类型,即 to void *(*)(void*),而不是void *

pthread_create(&thread, NULL, (void *(*)(void*)) thread_func, NULL);

但是,从 C 语言的角度来看,这绝不是安全的。POSIX 可以为您提供额外的保证,使其“更安全”,但无论如何我都不会这样做。

使用返回类型正确声明您的线程函数void *,并摆脱这种无用的黑客攻击。

于 2012-08-16T17:42:32.733 回答