0

这是我编写的一个函数:

uint32_t file_list(char *path, char ***ls){
    DIR *dp;
  //uint32_t i;
  struct stat fileStat;
  struct dirent *ep = NULL;
  uint32_t len, count = 0;
  int file = 0;
  *ls = NULL;
  dp = opendir (path);
  if(dp == NULL){
    fprintf(stderr, "no dir: %s\n", path);
    exit(1);
  }

  ep = readdir(dp);
  while(NULL != ep){
    count++;
    ep = readdir(dp);
  }
  rewinddir(dp);

  *ls = calloc(count, sizeof(char *));
  count = 0;
  ep = readdir(dp);
  while(ep != NULL){
    if((file = open(ep->d_name, O_RDONLY)) < 0){
      perror("apertura file");
      exit(1);
    }
    if(fstat(file, &fileStat) != 0){
      perror("filestat");
      free(*ls);
      close(file);
      exit(EXIT_FAILURE);
    }
    close(file);
    if(S_ISDIR(fileStat.st_mode)){
      len = strlen(ep->d_name);
      (*ls)[count] = malloc(len+5); /* lunghezza stringa + "DIR \n" */
      strcpy((*ls)[count], "DIR "); /* copio DIR */
      strcat((*ls)[count++], ep->d_name); /* concateno la stringa DIR con il nome della dir */
      ep = readdir(dp);
    }
    else{
      (*ls)[count++] = strdup(ep->d_name);
      ep = readdir(dp);
    }
  }
  /*for(i=0; i<count; i++){
    free((*ls)[count]);
  }*/
  (void)closedir(dp);
  return count;
}

进入我拥有的主程序char **files,然后我得到计数​​的部分count = file_list("./", &files);
是我的问题是什么?
每个人都知道它们(指针)可能引用的动态分配的内存必须被释放,但如果我释放指针(使用 for 循环)然后进入主程序,我在文件列表期间出现意外行为(重复的文件名,没有文件名等)
实际上,如果我不释放指针,所有指针都可以正常工作。
所以我的问题是:如何释放这些指针?
提前致谢!

4

4 回答 4

2

所有人都知道必须释放指针,但如果我释放指针(使用 for 循环)然后进入主程序,我在文件列表期间会出现意外行为(重复文件名、无文件名等)。

你的问题是你在同一个函数中分配和释放,这使得你的函数基本上没用(如果我理解正确的话)。如果你在同一个函数中释放,在它返回之后(即:在“主程序”中),你最终会访问已经释放给操作系统的内存段,这是未定义的行为。

您需要两个函数,一个用于分配(上面的一个),一个用于在完成后释放它,例如:

char** files;
uint32_t count = file_list("./", &files);
// do something with files here
file_list_free(&files, count);

请记住,您的自由函数需要知道count以防止缓冲区溢出。

您的代码还有其他问题(例如:不检查 的返回值calloc等),但是在这里涵盖所有问题会太长(并且不一定与您的实际问题相关)。

于 2012-08-09T16:28:35.727 回答
1

For starters, your ls parameter is a char***, so if that's what you were going for, you need to have an inner loop to free up all of the inner pointers (**ls) before freeing up each of the other ones (*ls). If you only want double indirection on ls, then get rid of one of the *s in your parameter declaration.

(BTW, you needn't use array notation in your loop to free up the pointers (or anywhere else that you access the allocated elements in ls). free(*(ls + count)); is usually the more accepted idiom. Pointer arithmetic works regardless of what the data type is (other than void), because the compiler takes that into account.)

于 2012-08-09T16:16:33.417 回答
1

您必须定义一个额外的函数,以便调用者在使用完数据后释放数据:

void free_file_list(char ***ls, int count) {
    for(int i=0; i<count; i++){
        free((*ls)[i]);
    }
    free(*ls);
}

然后,您的文档必须说明每个调用file_list必须与调用匹配free_file_list

不过,我会存储count在这样的结构中:

struct {
    char ***ls;
    int count;
} FILE_LIST;
于 2012-08-09T16:28:52.997 回答
0

使用完指针后,释放主程序中的指针。

You need to free *ls as well (again, after you've finished with it).

于 2012-08-09T16:15:41.387 回答