递归遍历目录函数出现无限循环问题求助
目录递归遍历问题分析与修复
你当前的代码存在多个核心错误,直接导致了无限阻塞/递归的问题,以下是具体问题和修复方案:
核心错误点
- 未处理
.和..特殊目录:递归遍历如果不跳过当前目录(.)和父目录(..),会陷入无限循环(比如访问..回到父目录后再次遍历当前目录)。 readdir未循环更新:代码仅在开头调用一次readdir(dir),循环内没有更新de的值,导致永远处理同一个目录项,形成死循环。- 内存分配与字符串操作错误:
- 分配字符数组时错误使用
sizeof(char*),应该用sizeof(char); memset传入字符串指针"\0"而非字符'\0',且错误使用sizeof(parent_name)(指针大小)而非实际分配的MAXSIZE;- 目录路径拼接未添加分隔符
/,导致路径无效; snprintf调用缺少长度参数,且逻辑错误地将路径拼回原缓冲区,引发溢出。
- 分配字符数组时错误使用
- 返回值类型不匹配:函数声明为
char*,但实际需要返回存储多个路径的char**数组;当前result是单个字符串,无法存储多个目录路径。 lstat路径错误:直接使用d_name(相对路径)调用lstat,在递归子目录时会找不到文件,需使用完整路径。- 内存管理混乱:链表节点分配冗余内存,指针赋值导致悬空引用,多处内存泄漏。
修复后的代码实现
以下是修正后的递归遍历函数,返回动态分配的char**数组(最后一个元素为NULL标记结束),同时跟踪目录层级:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/stat.h> #define MAXSIZE 1024 // 辅助函数:将新路径添加到结果数组中 char** append_path(char** paths, const char* path, int* count) { // 重新分配内存,增加一个元素(最后留NULL位置) paths = realloc(paths, sizeof(char*) * (*count + 2)); if (!paths) { perror("realloc failed"); exit(EXIT_FAILURE); } // 分配路径内存并复制 paths[*count] = malloc(strlen(path) + 1); if (!paths[*count]) { perror("malloc failed"); exit(EXIT_FAILURE); } strcpy(paths[*count], path); (*count)++; paths[*count] = NULL; // 标记结束 return paths; } // 递归遍历目录:返回存储所有子目录的char**数组,最后一个元素为NULL char** search_dir(const char* directory, int depth, int* count) { DIR* dir = opendir(directory); if (!dir) { perror("opendir failed"); return NULL; } struct dirent* de; struct stat st; char** result = NULL; // 先将当前目录加入结果 result = append_path(result, directory, count); while ((de = readdir(dir)) != NULL) { // 跳过.和.. if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) { continue; } // 拼接完整路径 char full_path[MAXSIZE]; snprintf(full_path, sizeof(full_path), "%s/%s", directory, de->d_name); // 获取文件状态 if (lstat(full_path, &st) == -1) { perror("lstat failed"); continue; } // 如果是目录,递归遍历 if (S_ISDIR(st.st_mode)) { char** sub_result = search_dir(full_path, depth + 1, count); if (sub_result) { // 合并子结果到当前结果 for (int i = 0; sub_result[i] != NULL; i++) { result = append_path(result, sub_result[i], count); free(sub_result[i]); // 释放子结果的单个路径 } free(sub_result); // 释放子结果数组 } } } closedir(dir); return result; } // 使用示例 int main() { int count = 0; char** dirs = search_dir("/path/to/your/dir", 0, &count); if (dirs) { for (int i = 0; dirs[i] != NULL; i++) { printf("目录路径: %s\n", dirs[i]); free(dirs[i]); } free(dirs); } return 0; }
关键修复说明
- 处理特殊目录:通过
strcmp跳过.和..,避免无限递归。 - 正确循环
readdir:在while条件中每次调用readdir(dir),遍历所有目录项。 - 路径拼接:使用
snprintf添加/分隔符,确保路径有效。 - 返回类型修正:使用
char**存储多个路径,用NULL标记数组结束,通过count参数跟踪路径数量。 - 内存管理:使用
realloc动态扩展结果数组,每个路径单独分配内存,使用后逐一释放避免泄漏。 lstat使用完整路径:确保在任何目录下都能正确获取文件状态。
内容的提问来源于stack exchange,提问作者David Power
相关产品推荐
相关产品推荐

