You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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++;
}

额外优化建议

  1. 修复僵尸进程问题:原代码中父进程仅等待最后一个子进程,其余子进程会变成僵尸进程,可替换为循环等待所有子进程:
// 替换原有的waitpid调用
while (wait(NULL) != -1);
  1. 检查malloc结果:避免malloc失败导致的空指针操作:
char* command = (char*) malloc(...);
if (command == NULL) {
    perror("malloc failed");
    exit(EXIT_FAILURE);
}
  1. 释放内存:使用完command后调用free(command),避免内存泄漏。

内容的提问来源于stack exchange,提问作者FreeZe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 08:10:47