pthread_create参数传递错误:传入下标0却写入数组索引1问题排查
问题根因
该问题属于线程参数传递的经典竞态条件,核心错误是直接将循环局部变量i的地址传递给了线程函数:
- 主线程中
i是栈上的局部变量,所有创建出的线程共享同一块内存地址 pthread_create仅提交线程创建请求,不会等待线程启动执行就会立刻返回,主线程会继续推进循环逻辑,执行i++操作- 你给出的测试代码中循环仅执行1次,
i初始值为0,创建线程后循环判断i < 1不再成立,退出前i会自增为1,此时线程才启动读取arg指向的值,拿到的自然是1,因此写入了patients[1]位置
修复方案
方案1:值传递(推荐用于小整数参数传递)
利用指针的存储宽度直接存放整数值,不需要传递地址,完全避免竞态:
- 主线程创建线程时修改传参逻辑:
pthread_create(&patients[i].thread, NULL, ®istration, (void*)i)
- 线程函数内修改取值逻辑:
int p_num = (int)arg;
该写法符合POSIX线程标准要求,常规32/64位系统下int长度均小于等于指针长度,可安全使用
方案2:动态申请内存传参(适合传递复杂参数)
每次循环单独申请一块内存存储索引值,线程用完后释放,避免共享变量:
- 主线程循环内修改:
for (size_t i = 0; i < 1; i++) { int* idx = malloc(sizeof(int)); *idx = i; if (pthread_create(&patients[i].thread, NULL, ®istration, idx) != 0) { perror("There has been an error with pthread_create()."); free(idx); return 1; } }
- 线程函数内修改:
void* registration(void* arg) { int p_num = *((int*)arg); free(arg); // 剩余原有逻辑不变 }
该方案需要注意内存释放,避免出现内存泄漏
内容的提问来源于stack exchange,提问作者covenant
相关产品推荐
相关产品推荐

