我尝试用这样的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 *是否安全?
答案 0 :(得分:3)
没有。您的代码will crash on IA64。函数指针强制转换为a bug waiting to happen。只需使用正确的签名并返回一个虚拟值,如0。
另请注意,将函数指针(如void (*)(void*)
)转换为对象指针(如void*
)也是一种潜在的不安全操作,因为C标准不保证对象指针和函数指针具有相同的表示。我不知道任何使用不同表示形式的架构,但是函数指针当然可能包含通常不存在于对象指针中的额外上下文位。
所以你永远不应该把一个函数指针强制转换为一个对象指针,除非你正在使用一个明确允许它的实现 - 例如,POSIX systems require这个,所以dlsym(3)
的返回值可以是从对象指针安全地转换为函数指针。
答案 1 :(得分:2)
在这种情况下将thread_func转换为void *是安全的
这可能适用于许多平台,但你应该知道:
void *
能够存储对象指针而非函数指针void *
并且没有完全合法的方法。例如,我想知道当pthread_join
具有非NULL结果时会发生什么指向void的指针可以转换为指针或从指针转换为any 对象类型。指向任何对象类型的指针可以转换为 指向void并再次返回;结果应该等于 原始指针。
当然:
指向一种类型的函数的指针可以转换为指向a的指针 另一种类型的功能又回来了;结果应该比较 等于原始指针。如果转换的指针用于调用 一个类型与引用类型不兼容的函数, 行为未定。
答案 2 :(得分:0)
虽然C编译器传统上比C ++编译器更加宽松(当涉及到隐式执行危险的指针转换)时,我发现很难相信任何C编译器都允许你为函数提供void *
参数指针参数,不会产生大量诊断消息。你有没有忘记包含pthread.h
,从而迫使前C99编译器推断出参数类型而不依赖于pthread_create
的函数原型?
在任何情况下,如果你真的想依赖这个hack,至少把指针指向正确的目标类型,即void *(*)(void*)
,而不是void *
pthread_create(&thread, NULL, (void *(*)(void*)) thread_func, NULL);
然而,从C语言的角度来看,它绝不是安全的。 POSIX可以为您提供额外的保证,使其“更安全”,但无论如何我都不会这样做。
使用void *
返回类型正确声明你的线程函数,并摆脱这个无用的黑客攻击。