如何正确释放C语言中的char **table

6

我需要你对这段代码提出建议: 表格字段options[0],options[1]等似乎没有正确释放。 感谢您的回答。

int main()
{
  ....
  char **options;
  options = generate_fields(user_input);
  for(i = 0; i < sizeof(options) / sizeof(options[0]); i++)  {
    free(options[i]);
    options[i] = NULL;
  }

  free(options);
}

char ** generate_fields(char *) 
{
   char ** options = malloc(256*sizeof(char *));
   ...
   return options;

}
3个回答

18

问题在于:

for(i = 0; i < sizeof(options) / sizeof(options[0]); i++)

options是指针类型,而不是数组类型,因此sizeof(options)始终相同(在32位机器上通常为4个字节,在64位机器上为8个字节),所以sizeof(options)/sizeof(options[0])几乎总是等于1。

关键在于释放内存的方式应该与malloc分配内存时一致。 所以,如果你使用malloc分配了一个二维数组,然后又分配了一系列一维数组,那么在释放内存时需要反过来:

char ** generate_fields(char *) 
{
   char ** options = malloc(256*sizeof(char *));
   for(int i = 0; i < 256; i++)
       options[i] = malloc(some_size);
   return options;
}

void free_fields(char ** options)
{
    for(int i = 0; i < 256; i++)
        free(options[i]);
    free(options);
}
注意,如果大小(在这种情况下为256)不是常量,则需要自己跟踪它,否则在释放时您将无法知道需要循环多少次。

如果大小(256)不是一个常量,你能否使用空终止数组来代替跟踪它的长度? - Snitse

7

你应该拥有与 malloc 相同数量的 free

在你的代码中,你分配了指针数组,但是你没有为数组的各个元素分配任何内存。但你的释放代码却像你已经这样做了。


3

我想在Adam的回答中补充一些内容,因为这可能无法在评论中完全表达。Adam是完全正确的。不过我怀疑你的generate_fields函数实际上可能会从用户那里获取输入,但我不确定。无论如何,有两种方法可以解决这个问题:

char ** generate_fields(char *, int num_fields, int size_of_field) 
{
   char ** options = malloc(num_fields*sizeof(char *));
   for(int i = 0; i < num_fields; i++)
       options[i] = malloc(size_of_field);
   return options;
}

还有一个对应的免费函数,为了简洁起见我会省略它。你可以看到正在发生什么-我们正在传入字段数量和字段大小。根据需要进行更改。另一个选择是使生成的字段将数组大小返回给调用它的程序。我会这样做:

int generate_fields(char** options) 
{
   int num_fields = 0;
   // somewhere here we get num_fields
   options = malloc(num_fields*sizeof(char *));
   for(int i = 0; i < num_fields; i++)
       options[i] = malloc(size_of_field);
   return num_fields;
}

你可以像这样从主函数调用:

int main()
{
    int sizeofarray = 0;
    char** fields;
    sizeofarray = generate_fields(fields);

或者如果您不喜欢那种表示方式,您总可以坚持自己原来的方式:

char** generate_fields(int* size) 

作为函数原型(这次返回选项并在代码中某处执行size=,然后从主函数中调用它,如下所示:
int sizeofarray = 0;
char** options;
options = generate_fields(&sizeofarray);

希望这能给你一些灵感,Adam。如果有必要,请随意编辑这些内容并将其添加到你的答案中。毕竟这些内容来自于你的回答。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接