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

