CLion WSL环境中链接math.h库触发Segmentation fault求助
使用math.h的ceil/log10函数导致段错误的修复方案
问题场景
编写了一段调用math.h中ceil和log10函数的C程序,在CLion的WSL环境下编译运行时出现Segmentation fault,将num_of_digits替换为常量值后程序可正常运行。CMakeLists.txt已配置链接数学库m。
程序代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <wait.h> #include <sys/types.h> #include <pthread.h> #include <math.h> #include <string.h> void count_lines(short unsigned int G); int main(int argc, char* argv[]) { count_lines(18); return 0; } void count_lines(short unsigned int G) { int status,g=0; pid_t pid; do{ pid = fork(); if(pid ==0) g++; }while(g<G && pid ==0 ); waitpid(pid, &status, 0); int num_of_digits = ceil(log10(g) +1); char* command = (char*) malloc(sizeof(char) * (strlen("grep \"generation is ") + num_of_digits +strlen("\" out.txt ") + strlen("| wc -l")+1)); sprintf(command,"grep \"generation is %d\" out.txt| wc -l", g); printf("%s\n" , command); }
CMake配置
cmake_minimum_required(VERSION 3.24) project(HW1 C) set(CMAKE_C_STANDARD 99) add_executable(HW1 main.c) target_link_libraries(${PROJECT_NAME} m)
错误输出
grep "generation is 18" out.txt| wc -l grep "generation is 17" out.txt| wc -l grep "generation is 16" out.txt| wc -l grep "generation is 15" out.txt| wc -l grep "generation is 14" out.txt| wc -l grep "generation is 13" out.txt| wc -l grep "generation is 12" out.txt| wc -l grep "generation is 11" out.txt| wc -l grep "generation is 10" out.txt| wc -l grep "generation is 9" out.txt| wc -l grep "generation is 8" out.txt| wc -l grep "generation is 7" out.txt| wc -l grep "generation is 6" out.txt| wc -l grep "generation is 5" out.txt| wc -l grep "generation is 4" out.txt| wc -l grep "generation is 3" out.txt| wc -l grep "generation is 2" out.txt| wc -l grep "generation is 1" out.txt| wc -l /bin/bash: line 1: 5353 Segmentation fault (core dumped) /mnt/c/Users/itzik/Documents/OperatingSystems/HW1/cmake-build-debug/HW1 Process finished with exit code 139
问题根源
段错误的直接原因是原始父进程中g=0,调用log10(0)触发未定义行为:
log10(0)会返回负无穷(-inf),后续计算ceil(-inf +1)结果还是负无穷- 将负无穷转换为
int类型会得到一个极大的负数,导致malloc传入的大小为负数 malloc接收负数参数时会返回NULL,后续sprintf往NULL指针写入内存,触发段错误
注:父进程的g始终为0,因为只有子进程(pid==0)才会执行g++操作。
修复方案
方案1:处理g=0的特殊情况
在计算数字位数时先判断g是否为0,避免调用log10(0):
int num_of_digits; if (g == 0) { num_of_digits = 1; // 0本身是1位数字 } else { num_of_digits = ceil(log10(g) + 1); }
方案2:用纯整数运算计算位数(更可靠)
完全避免浮点运算,通过循环计算整数的位数,不存在浮点精度或特殊值问题:
int num_of_digits = 1; unsigned int temp = g; while (temp >= 10) { temp /= 10; num_of_digits++; }
额外优化建议
- 修复僵尸进程问题:原代码中父进程仅等待最后一个子进程,其余子进程会变成僵尸进程,可替换为循环等待所有子进程:
// 替换原有的waitpid调用 while (wait(NULL) != -1);
- 检查malloc结果:避免
malloc失败导致的空指针操作:
char* command = (char*) malloc(...); if (command == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); }
- 释放内存:使用完
command后调用free(command),避免内存泄漏。
内容的提问来源于stack exchange,提问作者FreeZe
相关产品推荐
相关产品推荐

