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

C语言递归解析目录的函数出现Segmentation fault段错误如何解决

目录大小统计程序修复方案

核心问题及修复点

  • 段错误根因:递归传参错误:你检测到子目录后,递归调用时错误传入了当前父目录路径name,而非拼接好的子目录路径help,导致程序无限遍历同一个目录,栈溢出触发段错误,修改为传入help即可解决核心崩溃问题。
  • 栈空间滥用:递归函数内声明char help[1000000]会导致每个递归栈帧占用1MB内存,目录层级稍深就会耗尽栈空间,建议改用系统定义的最大路径长度PATH_MAX(一般为4096字节)。
  • 空指针访问风险:
    • getFileSize未判断fopen返回值,无权限打开文件时会得到空指针,后续操作直接崩溃,需增加合法性判断
    • getAllSize中opendir失败时dir为NULL,直接调用closedir会访问空指针,需仅在dir非空时执行关闭操作
  • 逻辑错误:递归得到的子目录大小没有累加进总大小,最终统计结果错误,需要接收递归返回值累加至当前size
  • 溢出风险:用int存储文件大小,超过2GB的文件会溢出,建议改用long long类型存储大小
  • 冗余逻辑漏洞:isDirectory末尾的closedir永远不会执行,且opendir失败返回-1的场景未处理,会导致无权限目录被误判为文件,引发后续错误。

修正后代码

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>

// 改用stat判断目录更高效,避免重复opendir
int isDirectory(const char* path) {
    struct stat st;
    if (stat(path, &st) != 0) {
        return -1;
    }
    return S_ISDIR(st.st_mode) ? 1 : 0;
}

long long getFileSize(const char* fileName) {
    FILE* file = fopen(fileName, "rb");
    if (file == NULL) {
        // 打开失败直接返回0,可根据需求调整错误处理逻辑
        return 0;
    }
    fseek(file, 0, SEEK_END);
    long long size = ftell(file);
    fclose(file);
    return size;
}

long long getAllSize(const char* dirName) {
    DIR* dir = opendir(dirName);
    if (dir == NULL) {
        return 0;
    }
    long long size = 0;
    struct dirent *dent;
    while((dent = readdir(dir)) != NULL) {
        // 跳过.和..
        if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) {
            continue;
        }
        char help[PATH_MAX];
        snprintf(help, sizeof(help), "%s/%s", dirName, dent->d_name);
        int dirRet = isDirectory(help);
        if (dirRet == 1) {
            // 传入子目录路径递归,累加返回的大小
            size += getAllSize(help);
        } else if (dirRet == 0) {
            size += getFileSize(help);
        }
        // dirRet为-1的场景(无权限等)直接跳过
    }
    closedir(dir);
    return size;
}

int main(int argc,char** argv) {
    // 可修改为从argv接收路径
    long long total = getAllSize("/home/rares/Documents/OS/Lab3");
    printf("总大小:%lld字节\n", total);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 10:15:04