9

我正在尝试将文件列表存储在 char** 变量中。

scandir() 正确完成,但在尝试打印 char** 时出现分段错误。

这是代码:

int main()
{
    char** fileList;
    int noOfFiles;
    char* path = ".";
    makeList(&fileList, &noOfFiles, path); 
    return 0;
}

void makeList(char ***fileList, int* noOfFiles, char* path){
    struct dirent **fileListTemp;
    *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);
    int i;
    fileList = (char***)malloc(sizeof(char***));
    *fileList = (char**)malloc(*noOfFiles * sizeof(char*));
    printf("total: %d files\n",*noOfFiles);
    for(i = 0; i < *noOfFiles; i++){
        *fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name) *sizeof(char));
        strcpy(*fileList[i], fileListTemp[i] -> d_name);
        printf("%s\n",*fileList[i]);
    }
    return;
}

这会在打印 2 个文件名后出现分段错误。

输出:

总计:27 个文件。

..

.jv

分段错误(核心转储)

4

4 回答 4

22

该函数scandir()为您分配内存。

您不需要分配任何内存。您确实需要释放由scandir().

您的代码调用: *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);

返回时,noOfFiles将包含目录中的目录条目数pathfileListTemp并将指向已分配的指针数组,这些指针指向已分配的struct dirent blob,每个 blob 都有一个d_name成员,该成员指向文件/目录的以 null 结尾的名称。

如果您的目录包含文件“FirstFile.txt”、“AnotherFile.txt”、“ThirdFile.txt”,例如,在您的调用中,在从 中返回时scandir(),三个文件noOfFiles将设置为5,再加上“ 。” 和“..”目录条目。如果您未通过“alphasort”,则参赛作品将不按特定顺序排列。(实际上这有点不正确。它们将按目录文件名条目的顺序排列,这取决于最初创建文件的顺序。)

因为您通过了 'alphasort',所以您应该按以下顺序看到条目(我明确显示了 null-byte-string-terminator:

fileListTemp[0]->d_name == ".\0"
fileListTemp[1]->d_name == "..\0"
fileListTemp[2]->d_name == "AnotherFile.txt\0"
fileListTemp[3]->d_name == "FirstFile.txt\0"
fileListTemp[4]->d_name == "ThirdFile.txt\0"

因此 fileListTemp 指向一个分配的内存块,其中包含五个struct dirent指针。五个struct dirent指针中的每一个都指向分配内存的struct dirent块,该内存块在d_name成员中包含一个以 null 结尾的目录条目名称。(这也是一种简化,因为 d_name 条目也是一个指针,但它指向分配块尾部的额外分配空间,条目名称存储在那里。)

那是分配内存的六个块。

你可以使用这个分配的内存,直到你完成它,然后你在数组中的每个条目上调用 free(),然后是数组本身的 free()。

您必须释放每个条目以及数组本身。它们都是独立分配的内存块。

完成列表后,您应该:

for (int i = 0; i < noOfFiles; i++)
  {
  free(fileListTemp[i];
  }

free(fileListTemp);
于 2014-02-07T00:32:05.267 回答
7

这是一个老问题,但由于我遇到它并且它没有像手册页那样有效地解决我的问题,所以我从手册页复制了一个代码片段作为未来的新答案。

  #include <dirent.h>

   int
   main(void)
   {
       struct dirent **namelist;
       int n;

       n = scandir(".", &namelist, NULL, alphasort);
       if (n < 0)
           perror("scandir");
       else {
           while (n--) {
               printf("%s\n", namelist[n]->d_name);
               free(namelist[n]);
           }
           free(namelist);
       }
   }
于 2014-09-04T22:09:45.497 回答
1

修改代码,可以了!

  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/dir.h>
  #include <stdlib.h>
  #include <string.h>

  void makeList(char ***fileList, int* noOfFiles, char* path){
      struct dirent **fileListTemp;
      *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);
      int i;
      *fileList = (char**)malloc(*noOfFiles * sizeof(char*));
      printf("total: %d files\n",*noOfFiles);
      for(i = 0; i < *noOfFiles; i++){
          (*fileList)[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name)+1);
          strcpy((*fileList)[i], fileListTemp[i] -> d_name);
          printf("%s\n",(*fileList)[i]);
      }   
      return;
  }

  int main()
  {
      char** fileList;
      int noOfFiles;
      char* path = ".";
      makeList(&fileList, &noOfFiles, path); 
      return 0;
  }

fileList是 的类型char ***,主函数*fileList中的变量也是。fileList

*fileList = (char**)malloc(*noOfFiles * sizeof(char*));

使用此语句,*fileList指向分配的指针数组内存。
如果要为数组中的每个指针分配内存,我们需要使用(*fileList)[i],除了*fileList[i], 的优先级[]高于*

于 2019-05-09T03:39:57.993 回答
0

我不确定这是不是问题,但您必须为空终止分配另一个字节:

*fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name + 1) *sizeof(char));
于 2013-08-23T12:14:10.067 回答