如何正确释放指针

时间:2012-08-09 15:57:37

标签: c function pointers

这是我写的一个函数:

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 个答案:

答案 0 :(得分:2)

  

永远知道指针必须被释放但是如果我释放指针(使用for循环)然后进入主程序我在文件列表中遇到了意外的行为(重复文件名,没有文件名等)。 / p>

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

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

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

请注意,您的免费功能需要知道count以防止缓冲区溢出。

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

答案 1 :(得分:1)

对于初学者来说,你的ls参数是char***,所以如果这就是你想要的,你需要有一个内循环来释放所有内部指针(**ls),然后释放其他每一个(*ls)。如果您只想在ls上进行双重间接,那么请在参数声明中删除其中一个*。

(顺便说一下,你不需要在你的循环中使用数组表示法来释放指针(或者你在ls中访问分配元素的任何其他地方)。free(*(ls + count));通常是更被接受的成语无论数据类型是什么(void除外),指针算法都可以工作,因为编译器会考虑到这一点。)

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

答案 3 :(得分:0)

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

你也需要释放*ls(再次,在你完成之后)。