如何在c中正确使用scandir()?

时间:2013-08-23 12:06:19

标签: c linux string malloc scandir

我正在尝试将文件列表存储在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个文件。

     

...

     

.j.v

     

分段错误(核心转储)

4 个答案:

答案 0 :(得分:16)

函数scandir()为你分配内存。

您无需分配任何内存。您 DO 需要释放scandir()返回给您的内存。

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

返回时,noOfFiles将包含path目录中的目录条目数,fileListTemp将指向已分配字符串的已分配字符串,每个字符串指向一个已分配的块,包含文件的以空值终止的名称。

如果您的目录包含文件“FirstFile.txt”,“AnotherFile.txt”,“ThirdFile.txt”,例如,通过您的电话,从scandir()返回后,noOfFiles将会是设置为 5 为三个文件加上另外两个为“。”和“..”目录条目。如果您不通过'alphasort',那么参赛作品将不会有任何特定的订单。 (实际上这有点不正确。它们将按目录文件名条目的顺序排列,这取决于最初创建文件的顺序。)

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

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

因此fileListTemp指向一个包含五个(char *)指针的已分配内存块。五个(char *)指针中的每一个都指向一个包含空终止目录条目名称的已分配内存块。

那是分配内存的 SIX 块。

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

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

完成列表后,您应该:

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

free(fileListTemp);

答案 1 :(得分:6)

这是一个老问题,但是由于我遇到它而且它没有像手册页那样有效地解决我的问题,我正在从man页面复制一个代码片段作为新的答案。将来

  #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);
       }
   }

答案 2 :(得分: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;
  }

fileListchar ***的类型,因此*fileList是主函数中的fileList变量。

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

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

答案 3 :(得分:0)

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

*fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name + 1) *sizeof(char));