制作一个列出目录中文件并对输出进行排序的程序
Making a program that lists files in a directory and sorts the output
我使用opendir(.)
打开一个路径到我想从中读取的目录。然后我使用 readdir
循环遍历当前目录中的所有文件和目录。然后我有一个 char**
列表来存储 readdir 的内容。然后我对 **list
进行排序以按字典顺序排列。仅当我有一个长度超过 63 个字符的文件时,我才在对输出进行排序时不断收到溢出错误。为什么会这样,我该如何解决?
void ls_short() {
char **list = NULL;
int count = 0;
DIR *dir;
struct dirent *rd;
dir = opendir(".");
// check to make sure that we can open the directory
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));
list[count] = rd ->d_name;
++count;
printf("%s\n",rd ->d_name);
}
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");
list = realloc(list, (count+1)*sizeof(*list));
list[count] = "";
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;
temp = (char*)calloc(count, sizeof(char)*256);
strcpy(temp, list[j]);
strcpy(list[j], list[j + 1]);
strcpy(list[j + 1], temp);
free(temp);
}
}
}
for (int i = 2; i < count;i++){
printf("%s\n",list[i]);
}
closedir(dir);
}
这是我收到的错误:
=================================================================
==43335==ERROR: AddressSanitizer: strcpy-param-overlap: memory ranges [0x6250000001fd,0x625000000220) and [0x62500000021d, 0x625000000240) overlap
#0 0x103ef03ef in wrap_strcpy+0xaf (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef)
#1 0x103e9aa5d in ls_short ls.c:61
#2 0x103e9a5c4 in main ls.c:16
#3 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)
0x6250000001fd is located 253 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
#0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
#1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
#2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
#3 0x103e9a6ad in ls_short ls.c:42
#4 0x103e9a5c4 in main ls.c:16
#5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)
0x62500000021d is located 285 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
#0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
#1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
#2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
#3 0x103e9a6ad in ls_short ls.c:42
#4 0x103e9a5c4 in main ls.c:16
#5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)
SUMMARY: AddressSanitizer: strcpy-param-overlap (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef) in wrap_strcpy+0xaf
==43335==ABORTING
Abort trap: 6
while((rd = readdir(dir)) != NULL){
list = realloc(list, (count+1)*sizeof(*list));
list[count] = rd ->d_name;
++count;
printf("%s\n",rd ->d_name);
}
您没有在任何地方分配内存来保存要添加到列表中的字符串。您分配内存来保存指向它的指针,仅此而已。
您需要将 list[count] = rd ->d_name;
更改为:
list[count] = malloc(256);
strcpy(list[count], rd->d_name);
此外,排序时不需要为字符串分配新的内存。如果您已经为每个需要存储的字符串分配了内存(您必须这样做,否则您的列表已经损坏),为什么更改顺序需要分配新内存来保存字符串?
readdir()
有一个用于 rd->d_name
的静态缓冲区,它会在您每次调用它时重复使用,因此您所有的 list
元素都指向同一个字符串。
将字符串分配给数组时,您应该复制这些字符串。
list[count] = strdup(rd->d_name);
并且在排序时,不要在字符串之间复制名称,只需交换指针即可。
if (strcasecmp(list[j], list[j + 1]) > 0) {
char* temp;
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
}
我使用opendir(.)
打开一个路径到我想从中读取的目录。然后我使用 readdir
循环遍历当前目录中的所有文件和目录。然后我有一个 char**
列表来存储 readdir 的内容。然后我对 **list
进行排序以按字典顺序排列。仅当我有一个长度超过 63 个字符的文件时,我才在对输出进行排序时不断收到溢出错误。为什么会这样,我该如何解决?
void ls_short() {
char **list = NULL;
int count = 0;
DIR *dir;
struct dirent *rd;
dir = opendir(".");
// check to make sure that we can open the directory
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));
list[count] = rd ->d_name;
++count;
printf("%s\n",rd ->d_name);
}
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");
list = realloc(list, (count+1)*sizeof(*list));
list[count] = "";
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;
temp = (char*)calloc(count, sizeof(char)*256);
strcpy(temp, list[j]);
strcpy(list[j], list[j + 1]);
strcpy(list[j + 1], temp);
free(temp);
}
}
}
for (int i = 2; i < count;i++){
printf("%s\n",list[i]);
}
closedir(dir);
}
这是我收到的错误:
=================================================================
==43335==ERROR: AddressSanitizer: strcpy-param-overlap: memory ranges [0x6250000001fd,0x625000000220) and [0x62500000021d, 0x625000000240) overlap
#0 0x103ef03ef in wrap_strcpy+0xaf (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef)
#1 0x103e9aa5d in ls_short ls.c:61
#2 0x103e9a5c4 in main ls.c:16
#3 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)
0x6250000001fd is located 253 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
#0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
#1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
#2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
#3 0x103e9a6ad in ls_short ls.c:42
#4 0x103e9a5c4 in main ls.c:16
#5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)
0x62500000021d is located 285 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
#0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
#1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
#2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
#3 0x103e9a6ad in ls_short ls.c:42
#4 0x103e9a5c4 in main ls.c:16
#5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)
SUMMARY: AddressSanitizer: strcpy-param-overlap (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef) in wrap_strcpy+0xaf
==43335==ABORTING
Abort trap: 6
while((rd = readdir(dir)) != NULL){
list = realloc(list, (count+1)*sizeof(*list));
list[count] = rd ->d_name;
++count;
printf("%s\n",rd ->d_name);
}
您没有在任何地方分配内存来保存要添加到列表中的字符串。您分配内存来保存指向它的指针,仅此而已。
您需要将 list[count] = rd ->d_name;
更改为:
list[count] = malloc(256);
strcpy(list[count], rd->d_name);
此外,排序时不需要为字符串分配新的内存。如果您已经为每个需要存储的字符串分配了内存(您必须这样做,否则您的列表已经损坏),为什么更改顺序需要分配新内存来保存字符串?
readdir()
有一个用于 rd->d_name
的静态缓冲区,它会在您每次调用它时重复使用,因此您所有的 list
元素都指向同一个字符串。
将字符串分配给数组时,您应该复制这些字符串。
list[count] = strdup(rd->d_name);
并且在排序时,不要在字符串之间复制名称,只需交换指针即可。
if (strcasecmp(list[j], list[j + 1]) > 0) {
char* temp;
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
}