调用pthread_join()后pthread_create()失效,线程tid为0致输出缺失
多线程程序输出缺失问题解决
问题概述
编写的多线程程序预期打印0到99的数字,但实际输出存在缺失。排查发现首次执行pthread_join()循环后,后续info[k].tid变为0,导致pthread_create()无法正常工作。
原代码
#include <pthread.h> #include <string.h> #include <stdlib.h> #include <stdio.h> typedef struct { pthread_t tid; int i; int res; } thread_info; void *square(void *data) { thread_info *info = (thread_info*) data; info->res = info->i; return NULL; } int main(void) { int nthread = 2; int lim = 100; int *results; results = calloc(lim, sizeof(int)); thread_info *info = calloc(nthread, sizeof(thread_info)); for (int i=0; i<lim; i++) { info[i % nthread].i = i; pthread_create(&info[i].tid, NULL, square, info + (i%nthread)); if (((i+1) % nthread)) { continue; } for (int k=0; k<nthread; k++) { pthread_join(info[k].tid, NULL); } for (int k=0; k<nthread; k++) { results[info[k].i] = info[k].res; } memset(info, 0, sizeof(thread_info) * nthread); } for (int i=0; i<100; i++) { printf("%d\n", results[i]); } return 0; }
问题根源
- 数组越界访问:
pthread_create的第一个参数错误传入&info[i].tid,但info数组仅分配了nthread(2)个元素。当i >= nthread时,info[i]属于越界访问,会破坏内存中的其他数据,导致tid被意外置0,引发未定义行为。 - 不必要的内存清零:
memset(info, 0, ...)会将所有线程信息结构体清零,包括tid字段,这一操作多余且会干扰后续线程创建的正确性。
修复方案
- 修正
pthread_create的第一个参数,改为&info[i%nthread].tid,确保始终访问info数组的有效索引。 - 移除不必要的
memset操作,下一轮循环会覆盖结构体中的i字段,tid也会被新的线程创建操作覆盖。 - 补充内存释放代码,避免内存泄漏。
修复后代码
#include <pthread.h> #include <string.h> #include <stdlib.h> #include <stdio.h> typedef struct { pthread_t tid; int i; int res; } thread_info; void *square(void *data) { thread_info *info = (thread_info*) data; info->res = info->i; return NULL; } int main(void) { int nthread = 2; int lim = 100; int *results; results = calloc(lim, sizeof(int)); thread_info *info = calloc(nthread, sizeof(thread_info)); for (int i=0; i<lim; i++) { int idx = i % nthread; info[idx].i = i; // 使用正确的索引获取tid地址,避免越界 pthread_create(&info[idx].tid, NULL, square, &info[idx]); if (((i+1) % nthread)) { continue; } for (int k=0; k<nthread; k++) { pthread_join(info[k].tid, NULL); } for (int k=0; k<nthread; k++) { results[info[k].i] = info[k].res; } } for (int i=0; i<100; i++) { printf("%d\n", results[i]); } // 释放分配的内存 free(results); free(info); return 0; }
内容的提问来源于stack exchange,提问作者s5s
相关产品推荐
相关产品推荐

