pthread_join返回值异常 多线程拆分求数组最小值结果错误
多线程拆分数组求全局最小值 问题修复
核心错误点
- 线程返回局部变量地址:
Find_min_val中返回栈上局部变量temp的地址,线程退出后栈空间会被系统回收,后续访问该地址属于未定义行为,读取到的值完全不可控。 - 子数组长度计算错误:指针无法通过
sizeof计算指向数组的长度,64位环境下该计算结果恒为2,和实际子数组长度没有任何关系。 - 奇偶判断逻辑错误:
if(k=0)是赋值操作而非相等判断,且偶数分支的halfArgc2=halfArgc2属于无效赋值。 - 子数组拷贝范围错误:第二个子数组的拷贝起始地址多减了1,导致两个子数组元素重叠,拆分逻辑完全错误。
- 结果存储下标错误:两个线程的返回值都存入
Min_Val[1],第一个线程的计算结果直接被覆盖。 - 未初始化变量访问:定义
arr后直接读取arr[0]给min赋值,此时arr还未填充数据,属于非法访问。
修复方案
自定义结构体传递子数组的起始地址和长度,返回值改用堆内存存储避免栈回收问题,同时修正拆分逻辑和结果存储逻辑:
修复后完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> // 自定义结构体传递线程参数:数组起始地址+长度 typedef struct { int *arr; int len; } ThreadArg; int min_value(int a[], int n) { int c, index = 0; for (c = 1; c < n; c++) if (a[c] < a[index]) index = c; return a[index]; } void* Find_min_val(void* arg) { ThreadArg *s = (ThreadArg*) arg; int numOfarray = s->len; // 打印子数组元素 for(int j=0; j<numOfarray; ++j) { printf("%d\n", s->arr[j]); } // 计算子数组最小值 int temp = min_value(s->arr, numOfarray); printf("Sub Min = %d\n", temp); // 用堆内存存储返回值,避免栈空间回收问题 int *ret = malloc(sizeof(int)); *ret = temp; return ret; } int main(int argc, char const *argv[]) { int j, element; int halfArgc1, halfArgc2, k = (argc-1) % 2; pthread_t tid1, tid2; if(argc <= 1) { fprintf(stderr, "Not enough arguments entered\n"); return 1; } // 填充输入数组 int arr[argc-1]; for(j=1; j<argc; j++) { element = atoi(argv[j]); arr[j-1] = element; } // 拆分数组 halfArgc1 = (argc - 1) / 2; if(k == 0) { halfArgc2 = halfArgc1; } else { halfArgc2 = halfArgc1 + 1; } int subArr1[halfArgc1], subArr2[halfArgc2]; memcpy(subArr1, arr, halfArgc1 * sizeof(int)); memcpy(subArr2, arr + halfArgc1, halfArgc2 * sizeof(int)); // 构造线程参数 ThreadArg arg1 = {.arr = subArr1, .len = halfArgc1}; ThreadArg arg2 = {.arr = subArr2, .len = halfArgc2}; if (pthread_create(&tid1, NULL, Find_min_val, (void*)&arg1)) return 1; if (pthread_create(&tid2, NULL, Find_min_val, (void*)&arg2)) return 1; int* r; int Min_Val[2]; if (pthread_join(tid1, (void**) &r)) { fprintf(stderr, "Could not join Thread 1\n"); return 1; } Min_Val[0] = *r; free(r); // 释放线程返回的堆内存 if (pthread_join(tid2, (void**) &r)) { fprintf(stderr, "Could not join Thread 2\n"); return 1; } Min_Val[1] = *r; free(r); printf("Global Min = [%d]\n", min_value(Min_Val, 2)); return 0; }
运行验证
执行命令:
gcc -pthread -o hw3 hw3.c ./hw3 1 2 3 4 5
输出结果:
1 2 Sub Min = 1 3 4 5 Sub Min = 3 Global Min = [1]
内容的提问来源于stack exchange,提问作者lst
相关产品推荐
相关产品推荐

