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

closedir()引发已有链表节点变更:二次调用listFilesInDirectory函数异常

问题根源分析

你遇到的这个问题,核心原因并不是closedir()本身,而是**readdir()返回的dirent结构体里的d_name指向的是一块复用的缓冲区**,不是为每个文件名单独分配的独立内存。

当你第一次调用listFilesInDirectory时,链表节点里保存的其实是指向DIR内部缓冲区的指针,而不是文件名的副本。第二次调用readdir()(在第二个函数调用里)时,系统会复用这块缓冲区,把新的文件名写进去,这就导致之前sourceFiles链表中所有节点的d_name指针指向的内容被覆盖了——看起来像是第二次调用修改了旧链表的内容。closedir()可能会释放这块缓冲区,但即使不调用它,只要再次调用readdir(),缓冲区内容就会被改写。

修复方案

解决方法很简单:在创建节点的时候,复制一份文件名的内容到独立分配的内存中,而不是直接保存d_name的指针。你可以用标准库的strdup()函数(它会自动分配内存并复制字符串),或者手动用malloc()+strcpy()实现。

修改后的listFilesInDirectory函数如下:

myList* listFilesInDirectory(char* path) { 
    DIR* dir = opendir(path); 
    if (!dir) { // 增加错误判断,避免空指针崩溃
        return NULL;
    }
    myList* list = createList(); 
    struct dirent* entry; 
    while ((entry = readdir(dir)) != NULL) { 
        // 复制文件名到新内存,再传给createNode
        char* fileName = strdup(entry->d_name);
        if (fileName) { // 检查内存分配是否成功
            myNode* node = createNode(fileName); 
            addToList(list, node); 
        }
    } 
    closedir(dir); 
    return list; 
}
额外注意事项
  • 如果你用了strdup(),记得在销毁链表节点的时候,要先释放fileName的内存,再释放节点本身,避免内存泄漏。比如在destroyNode函数里,要调用free(node->data)(假设你的节点数据是保存的文件名指针)。
  • 一定要加错误判断:比如opendir()可能失败(路径不存在、权限不够),strdup()也可能因为内存不足返回NULL,这些情况都要处理,避免程序崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:29:04