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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18402428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:38:46  来源:igfitidea点击:

How to properly use scandir() in c?

clinuxstringmallocscandir

提问by kBisla

I am trying to store list of files in a char** variable.

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

scandir() finishes properly but I get a segmentation fault when trying to print the char**.

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

Here's the code:

这是代码:

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

This gives a segmentation fault after printing 2 file names.

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

output:

输出:

total: 27 files.

..

.j.v

Segmentation fault (core dumped)

总计:27 个文件。

..

.jv

分段错误(核心转储)

采纳答案by kch_PE_MSEE_BSCE

The function scandir()allocates the memory for you.

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

You do not need to allocate ANY memory. You DOneed to free the memory returned to you by scandir().

您不需要分配任何内存。您确实需要释放由 返回给您的内存scandir()

Your code calls: *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);

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

On return, noOfFileswill contain the number of directory entries in the pathdirectory, and fileListTempwill point to an allocated array of pointers to allocated struct direntblobs each of which has a d_namemember which points to the null-terminated name of a file/directory.

返回时,noOfFiles将包含目录中目录条目的数量pathfileListTemp并将指向分配给已分配struct direntblob的指针数组,每个指针都有一个d_name成员,该成员指向文件/目录的以空字符结尾的名称。

If your directory contains the files "FirstFile.txt", "AnotherFile.txt", "ThirdFile.txt", for example, with your call, upon return from scandir(), noOfFileswill be set to 5for the three files plus two more for the "." and ".." directory entries. THE ENTRIES WILL BE IN NO PARTICULAR ORDER IF YOU DO NOT PASS 'alphasort'. (Actually that's a little incorrect. They will be in the order of the directory filename entries which depends on the order in which the files were originally created.)

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

Because you passed 'alphasort' you should see the entries in the following order (I am explicitly showing the null-byte-string-terminator:

因为您通过了 'alphasort',您应该按以下顺序查看条目(我明确显示了空字节字符串终止符:

fileListTemp[0]->d_name == ".
for (int i = 0; i < noOfFiles; i++)
  {
  free(fileListTemp[i];
  }

free(fileListTemp);
" fileListTemp[1]->d_name == "..
*fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name + 1) *sizeof(char));
" fileListTemp[2]->d_name == "AnotherFile.txt
  #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);
       }
   }
" fileListTemp[3]->d_name == "FirstFile.txt
  #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;
  }
" fileListTemp[4]->d_name == "ThirdFile.txt
*fileList = (char**)malloc(*noOfFiles * sizeof(char*));
"

So fileListTemp points to a block of allocated memory holding five struct direntpointers. Each of the five struct direntpointers points to a struct direntblock of allocated memory containing a null-terminated directory entry name in the d_namemember. (Even this is a simplification, because the d_name entry is also a pointer, but it points to extra allocated space at the tail end of the allocated block, and the entry name is stored there.)

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

That is SIXblocks of allocated memory.

那是六个分配的内存块。

You can use this allocated memory until you are done with it, and then you call free() on EACH entry in the array followed by free() of the array itself.

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

You MUST free every entry as well as the array itself. They are all independently allocated blobs of memory.

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

When you are done with the list you should:

完成列表后,您应该:

##代码##

回答by eyalm

I am not sure this is the problem, but you have to allocate another byte for the null termination:

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

##代码##

回答by merlin2011

This is an old question, but since I came upon it and it did not solve my question as effectively as the man page did, I am copying a code snippet from the manpage as a new answer for the future.

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

##代码##

回答by Hui Lee

modify the code, it works!

修改代码,成功!

##代码##

fileListis type of char ***, so *fileListis the fileListvariable in main function.

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

##代码##

with this statement, *fileListpoints to allocated memory of array of pointers.
if want to allocate memory for each pointer within the array, we need use (*fileList)[i], other than *fileList[i], the precedence of []is higher than *.

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