C多线程程序pthread_join触发Segmentation fault (core dumped)排查
段错误根源排查与修正
核心错误定位
你观察到的“pthread_join处触发段错误”只是问题的暴露位置,根因是前面的pthread_create调用已经传入了非法参数,具体错误点如下:
pthread_create(&num,NULL,foo(size),NULL)的传参逻辑完全错误:这里不是传入foo函数作为线程入口,而是在执行pthread_create时直接调用了foo(size),把foo的返回值(无合法返回值的野指针)当作pthread_create要求的函数指针类型的第三个参数传入。pthread_create拿到非法参数后根本没有创建成功的线程,返回的num句柄是无意义的随机值,后续用这个无效句柄调用pthread_join时自然触发段错误。- 线程入口函数的签名不符合POSIX标准要求:pthread规范要求线程入口必须是
void* 函数名(void* 通用参数)的形式,你写的void *foo(int kb)参数类型完全不匹配,哪怕正确传入函数指针,也会因为参数类型不对导致未定义行为。 - foo函数缺少合法返回值:作为返回void*类型的函数,foo执行完循环后没有任何return语句,编译时就会触发“隐式返回”的警告,函数退出时返回值寄存器存储的是随机值,属于明确的未定义行为。
- 你声明的
float etime();没有对应实现:如果没有链接对应功能的实现代码,第一次调用etime()时就会跳转到无效内存地址触发崩溃,和pthread本身无关。
修正后的正确代码逻辑
线程参数必须通过pthread_create的第四个void*类型参数传递,不能在创建线程时直接调用入口函数,参考关键修正片段:
// 符合POSIX规范的线程入口签名 void *foo(void *arg) { // 将通用参数转换为实际需要的类型 int kb = (int)(long)arg; printf("Allocating memory\n"); // 必须增加内存分配失败判断 buffer = calloc(kb, sizeof(char)); if (buffer == NULL) { perror("calloc failed"); pthread_exit(NULL); } printf("Memory allocated\n"); int i; printf("After i\n"); for(i = 0; i < kb; i++) { buffer[i] = 'z'; } printf("End of for loop\n"); // 规范的线程退出方式 pthread_exit(NULL); } void et(int size) { int thrr; pthread_t num; etime(); printf("Inside et \n"); printf("Before calling create thread \n"); // 正确传参:传入函数指针本身,将size值作为通用参数传递给线程 thrr = pthread_create(&num, NULL, foo, (void*)(long)size); printf("thrr = %d\n", thrr); if(thrr != 0) { printf("Cannot create thread!\n"); return; } printf("Thread created successfully\n"); // 此时num是pthread_create返回的合法句柄,调用join不会触发非法访问 pthread_join(num, NULL); printf("Time taken = %f\n", etime()); }
额外注意事项
- 64位系统下直接将int类型强转为void*存在整数截断风险,更严谨的传参方式是将size值存在堆内存中,把内存地址通过arg传入线程,线程处理完成后释放内存,避免栈变量失效、整数截断等问题。
- 编译多线程程序时需要链接pthread库,即使用
gcc 源文件.c -o test -lpthread,否则也会出现函数符号找不到导致的崩溃。
内容的提问来源于stack exchange,提问作者AnmolSingh
相关产品推荐
相关产品推荐

