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

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

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

假设它目前真的0,那又如何呢? 这预先假定pthread_t是算术类型,当前版本的 POSIX 未指定,但如果是这样,则 0 是它的有效值。 对于特定的线程标识符值,没有记录的重要性,特别是,如果线程是类型为pthread_t的有效值,则没有理由认为不应将线程分配 0 作为其标识符。

既然你还提到了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是算术或指针类型,强制转换就有效,在实践中,如果它是其他任何东西(例如结构类型),则可以依赖编译器来拒绝代码。 假设强制转换是获取已知类型所必需的(但可能还不够),则无符号类型更安全,因为如果原始值超出目标类型的范围,则转换已定义行为。 如果你有一个类型不匹配,就像你在原始代码中一样,那么行为是未定义的,在这种 UB 的无数种可能表现形式中,更有可能的是,尽管thread[0]为非零,但仍打印了"0"。

综上所述,我不会重现您的问题,即使使用您原始的、有缺陷的代码也是如此。 我倾向于怀疑您的pthread_create调用失败,可能是因为您使用的是在没有线程支持的情况下构建的 C 库,或者链接虚拟 pthreads 例程而不是功能例程。 确保在构建时为 pthreads 程序提供正确的选项。 例如,如果您使用gcc进行编译,则需要提供-pthread选项。 如果您有单独的编译和链接步骤,则对这两个步骤都使用该选项。

尝试将返回值与零进行检查。仅当返回值为 0 时,线程创建才会成功。

errno手册页显示"有效错误号都是正数"。例如,在 Linux 上,errno 错误号似乎大致在 0 到 200 之间。

另外,打印与您获得的 errno 错误号对应的消息,例如使用 perror()。

根据POSIX,pthread_t类型是不透明的。它可以是任何类型。特别是,它不需要是算术类型(指针或整数)。POSIX 线程的一致性实现可以使用struct进行pthread_t

如果pthread_t恰好是整数类型,则不禁止它为零。它可能是某个数组中线程的索引,以便第一个线程的位置为零。

毕竟,标准输入文件描述符为零并不感到惊讶。

最新更新