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

递归遍历目录函数出现无限循环问题求助

目录递归遍历问题分析与修复

你当前的代码存在多个核心错误,直接导致了无限阻塞/递归的问题,以下是具体问题和修复方案:

核心错误点

  • 未处理.和..特殊目录:递归遍历如果不跳过当前目录(.)和父目录(..),会陷入无限循环(比如访问..回到父目录后再次遍历当前目录)。
  • 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;
}

关键修复说明

  1. 处理特殊目录:通过strcmp跳过.和..,避免无限递归。
  2. 正确循环readdir:在while条件中每次调用readdir(dir),遍历所有目录项。
  3. 路径拼接:使用snprintf添加/分隔符,确保路径有效。
  4. 返回类型修正:使用char**存储多个路径,用NULL标记数组结束,通过count参数跟踪路径数量。
  5. 内存管理:使用realloc动态扩展结果数组,每个路径单独分配内存,使用后逐一释放避免泄漏。
  6. lstat使用完整路径:确保在任何目录下都能正确获取文件状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:17:57