C语言使用readdir列目录排序时长文件名溢出报错如何解决
错误原因
- 直接存储
readdir返回的d_name指针:readdir返回的struct dirent是C标准库内部的共享缓冲区,每调用一次readdir就会覆盖前一次的缓冲区内容。你直接把rd->d_name的指针存到list里,本质上所有数组元素都指向同一块内存区域,不同指针的地址区间本身就重叠,而且这块内存是库内部管理的,你没有修改权限,后续写入时直接触发报错。 - 排序交换逻辑错误:
list里存的是字符串指针,排序时只要交换指针本身的值就可以,完全不需要拷贝字符串内容。你现在用strcpy拷贝内容,一来写入了不可修改的库缓冲区,二来strcpy本身不支持源和目标地址重叠的场景,这是触发strcpy-param-overlap报错的直接原因。 - 额外的逻辑错误:你主动在
list末尾加了指向字符串常量""的指针,字符串常量是只读内存,排序时如果碰到这个元素执行写入操作会直接触发段错误。
修复方案
- 读取目录项时,主动拷贝
d_name的内容到自行申请的堆内存中,不要直接引用库的内部缓冲区指针。 - 排序时直接交换
char*指针的值,废弃字符串拷贝的逻辑,既提升性能也不会出现内存越界、重叠问题。 - 不需要额外添加空字符串到
list末尾,排序逻辑直接基于实际读取到的目录项数量count处理。 - 程序退出前释放所有申请的内存,避免内存泄漏。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <dirent.h> #include <string.h> #include <strings.h> void ls_short() { char **list = NULL; int count = 0; DIR *dir; struct dirent *rd; dir = opendir("."); // 检查目录是否打开成功 if(dir == NULL){ perror("Not able to open The current directory."); exit(EXIT_FAILURE); } while((rd = readdir(dir)) != NULL){ list = realloc(list, (count+1)*sizeof(*list)); // 拷贝d_name到自行申请的内存,不要直接存rd->d_name的指针 list[count] = strdup(rd->d_name); ++count; printf("%s\n",rd->d_name); } closedir(dir); // 目录读取完就可以关闭,不用等到最后 printf("here we will print the list\n"); for (int i = 0; i < count;i++){ printf("%s\n",list[i]); } printf("Now we print the list in order and also get rid of . and .. directory\n"); // 排序时直接交换指针,不需要拷贝字符串内容 for (int i = 0; i < count - 1; i++){ for (int j = 0; j < count - i - 1; j++){ if (strcasecmp(list[j], list[j + 1]) > 0) { char* temp = list[j]; list[j] = list[j+1]; list[j+1] = temp; } } } for (int i = 2; i < count;i++){ printf("%s\n",list[i]); } // 释放申请的内存,避免泄漏 for (int i = 0; i < count; i++) { free(list[i]); } free(list); }
内容的提问来源于stack exchange,提问作者NoseNatchos
相关产品推荐
相关产品推荐

