pthread_join()触发段错误问题排查:多线程幂次计算程序异常分析
问题分析与修复方案
嘿,我一眼就揪出了问题的根源——内存分配不足导致的越界访问,这是典型的未定义行为:有时候运气好能侥幸运行,有时候直接触发段错误给你看。
核心问题拆解
看你代码里的内存分配行:
powr = (double *)malloc(NUM_THREADS*10);
你需要存储100个double类型的平方值(10个线程×每个线程处理10个数),但malloc的参数是字节数。在绝大多数系统中,double占8字节,你这里只分配了10×10=100字节,远小于实际需要的100×8=800字节。
当线程写入powr[i]时,超过分配的内存区域后,会覆盖进程地址空间里的其他敏感数据(比如线程ID数组、栈上的变量或者线程管理的关键结构)。为什么只join前4个线程时没崩溃?纯粹是运气好——前4个线程写入的区域还没碰到底层关键数据;但join更多线程后,越界写入覆盖了敏感数据,直接触发段错误。
修复步骤
- 修正内存分配:给
malloc加上sizeof(double),确保分配足够的空间(另外C语言里不需要强制转换malloc的返回值,强制转换反而可能隐藏潜在问题):powr = malloc(NUM_THREADS * 10 * sizeof(double)); - 添加内存分配失败检查:这是良好的编程习惯,避免后续操作空指针:
if (powr == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); } - 可选优化:用整数乘法替代
pow函数,计算整数平方更高效,还能避免浮点运算的微小误差:powr[i] = (double)(i * i); // 或者直接写i*i,编译器会自动转换为double类型 - 别忘了释放内存:程序结束前释放
powr,避免内存泄漏。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #define NUM_THREADS 10 double *powr; void *pows(void *arg){ int n = *((int*)arg)*10; for(int i = n; i < n+10; i++){ powr[i] = (double)(i * i); // 替换pow函数,更高效准确 } return NULL; } int main(int argc, char *argv[]) { pthread_t thread_ID[NUM_THREADS]; int rank[NUM_THREADS], j; powr = malloc(NUM_THREADS * 10 * sizeof(double)); if (powr == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); } for(j = 0; j < NUM_THREADS; j++){ rank[j] = j; pthread_create(&thread_ID[j], NULL, pows, &rank[j]); } for(j = 0; j < NUM_THREADS; j++){ pthread_join(thread_ID[j], NULL); } for(j = 0; j < NUM_THREADS*10; j++){ printf("%.0lf ", powr[j]); } free(powr); // 释放内存,避免泄漏 return 0; }
内容的提问来源于stack exchange,提问作者T Boon den
相关产品推荐
相关产品推荐

