首页 > 解决方案 > pthread_t 什么时候为 0?

问题描述

我在 RHEL 7.2 中使用 pthread_create() 创建了线程。pthread_create 返回 0,但 *thread(第一个参数)为 0。

你知道线程id为0的原因吗?

pthread_t thread[6];
int nArg;

int nThread = pthread_create(&thread[0], NULL, funcA, &nArg);
if(0 > nThread)
    printf("failed");
else
    printf("thread started: %ld", thread[0]);

输出:线程启动:0

标签: pthreads

解决方案


我在 RHEL 7.2 中使用 pthread_create() 创建了线程。pthread_create 返回 0,但 *thread(第一个参数)为 0。

你知道线程id为0的原因吗?

暂时假设它真的0,那又如何呢?这假定这pthread_t是一个算术类型,当前版本的 POSIX 没有指定,但如果是这样,那么 0 是它的有效值。对于特定的线程标识符值没有记录的意义,特别是,如果线程的标识符是 type 的有效值,则没有理由认为不应将其分配为 0 作为其标识符pthread_t

既然您还提到了 的返回值pthread_create,我想您可能会认为它与线程 ID 之间存在某种关系。没有记录这样的关系,除了线程 ID 的pthread_create()值是在返回值恰好为 0 时在返回之后定义的。

但这确实指出了您的代码中的一个问题,@ErikAlapää 首先指出:pthread_create()在失败时直接返回错误号的函数组中,而不是在失败时返回 -1 并希望您咨询errno错误的组数字。错误编号是正数,因此if(0 > nThread)不能依赖您的条件来检测是否pthread_create失败。您应该针对 0 进行测试:

if (0 != nThread) {
    printf("failed");
} else {
    printf("thread started: %lu", (unsigned long) thread[0]);
}

printf()还要注意第二次调用中的格式更改和强制转换。您需要第二个参数具有与格式化指令(以前是%ld,但现在%lu)完全对应的类型,那就是unsigned long int. 只要pthread_t是算术或指针类型,强制转换就有效,实际上,如果代码是其他任何东西——比如结构类型,则可以依赖编译器来拒绝代码。鉴于强制转换对于获得已知类型是必要的(但可能还不够),无符号type 更安全,因为转换定义了在原始值超出目标类型范围的情况下的行为。如果您有类型不匹配,就像您在原始代码中可能遇到的那样,那么行为是未定义的,并且在这种 UB 的无数可能表现中,最有可能的是打印“0”,尽管thread[0]它是非零的。

尽管如此,我不会重现您的问题,即使您使用有缺陷的原始代码也是如此。我倾向于怀疑你的pthread_create调用失败了,可能是因为你使用了一个没有线程支持的 C 库,或者链接了虚拟 pthreads 例程而不是函数式例程。确保在构建时为 pthreads 程序提供正确的选项。例如,如果您正在编译,gcc那么您将希望提供该-pthread选项。如果您有单独的编译和链接步骤,请同时使用该选项。


推荐阅读