2010-03-20 129 views
4

我需要你对这段代码的建议: 表字段选项[0],选项[1]等......似乎没有被正确释放。 谢谢您的回答如何正确地释放C表中的char **表

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; 

} 

回答

14

问题是这样的:

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

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

关键是总是free内存方式与你malloc'编辑它。因此,如果您malloc 2维数组,然后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在这种情况下)是不是一个常数,你需要自己跟踪它,因为否则你无法知道释放多少次循环。

+0

如果大小(256)不是一个常量,难道你不能终止数组,而不是跟踪它是多久? – Snitse 2011-12-28 19:51:09

7

你应该有相同数量的free S作为你malloc秒。

在你的代码中你分配了指针数组,但是你没有为数组的单个元素指定任何内存来指向它。但是你的解放代码就像你写的一样。

3

我打算在此添加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=,并且从main调用如下:

int sizeofarray = 0; 
char** options; 
options = generate_fields(&sizeofarray); 

希望给你一些更多的想法,亚当,随意编辑任何/所有这些到你的答案适当的,无论如何它来自你的答案。