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
相关产品推荐
相关产品推荐

