pthread_t什么时候有0?

When does pthread_t have 0?

我在 RHEL 7.2 中使用 pthread_create() 创建了线程。 pthread_create returns 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

尝试检查 return 值是否正好为零。只有return值为0才创建线程成功。

errno 联机帮助页显示 'Valid error numbers are all positive numbers'。例如,在 Linux 上,errno 错误编号似乎大致在 0 到 200 之间。

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

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

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

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

I created threads using pthread_create() in RHEL 7.2. pthread_create returns 0, but *thread (1st parameter) is 0.

do you know the reason that thread id is 0?

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

既然你也提到了pthread_create的return值,我想你可能认为这与线程ID之间存在某种关系。没有记录这种关系,除了线程 ID 的值在 pthread_create() return 之后定义,仅当 return 值恰好为 0 时。

但这确实指出了您代码中的一个问题,@ErikAlapää 首先指出:pthread_create() 属于 return 直接在失败时出现错误编号的函数组,不是 return -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 是算术或指针类型,转换就有效,并且在实践中,如果它是任何其他类型(例如,结构类型),则可以依靠编译器拒绝代码。鉴于强制转换对于获得已知类型是必要的(但可能不充分),unsigned 类型更安全,因为转换在原始值超出的情况下定义了行为目标类型的范围。如果您有类型不匹配,就像您在原始代码中可能遇到的那样,那么行为是未定义的,并且在这种 UB 的无数可能表现中,最有可能的是尽管 thread[0] 打印了“0”非零。

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