C内存泄漏(尽管可用)

C内存泄漏(尽管可用),c,memory,pointers,valgrind,C,Memory,Pointers,Valgrind,在用Valgrind调试我的程序时,我发现了一个内存泄漏,尽管我认为这是有效的释放调用。首先,分配并存储内存的代码: row = malloc(sizeof(Row)); row->columns = malloc(sizeof(char*) * headcnt); row->numcol = 0; ... row->numcol = colcnt; rows = realloc(rows, (ro

在用Valgrind调试我的程序时,我发现了一个内存泄漏,尽管我认为这是有效的释放调用。首先,分配并存储内存的代码:

    row = malloc(sizeof(Row));
    row->columns = malloc(sizeof(char*) * headcnt);
    row->numcol  = 0;

    ...

    row->numcol    = colcnt;
    rows           = realloc(rows, (rowcnt+1) * sizeof(Row));
    rows[rowcnt++] = *row;
负责尝试释放内存的代码:

void cleanUp(){
    int i = 0;
    int j = 0;

    for (i = 0; i < rowcnt; i++){
        for (j = 0; j < rows[i].numcols; j++){
            free(rows[i].columns[j]);
        }
        free(&rows[i]);
    }
    free(rows); 
    exit(0);
}

更糟糕的是,该程序有时会在
free(&rows[i])
处导致glibc错误,从而导致双自由。我是C语言的新手,如果有人能给我指点一下,我会很感激的。

也许我很笨,但这不是完全没有必要吗?无论如何,只要程序退出,所有内存都将被释放。

malloc
(或
realloc
)的每次调用都必须与对
free
的相应调用相匹配。如果这样动态分配阵列:

int *p = malloc(sizeof(int) * NUM);
您可以这样释放它:

free(p);
for (int i = 0; i < NUM; i++)
{
    free(p[i]);
}
不是这样的:

free(p);
for (int i = 0; i < NUM; i++)
{
    free(p[i]);
}

执行
行[rowcnt++]=*行有效地复制您分配的内存。数组行应该是指针数组。正如Oli Chalesworth所指出的,您对列的空闲应该是对所有列的单个空闲

rows = malloc(count * sizeof(Row*)); // This is probably done somewhere

row->columns = malloc(sizeof(char*) * headcnt);
row->numcol  = 0;

...

row->numcol    = colcnt;
rows           = realloc(rows, (rowcnt+1) * sizeof(Row*));
rows[rowcnt++] = row;
现在如果你的清理工作

void cleanUp(){
    int i = 0;
    int j = 0;

    for (i = 0; i < rowcnt; i++){
        free(rows[i]->columns);
    }
    free(rows); 
    exit(0);
}
void cleanUp(){
int i=0;
int j=0;
对于(i=0;i列);
}
自由(行);
出口(0);
}

您需要包含行类型的声明。可以在此处使用更多代码。现在我有点困惑,为什么要为一行中的每一列设置
malloc
空间,然后将row->numcol设置为零。
free()
知道
malloc()
分配的内存块大小,并将释放整个块。看起来您正在对块进行迭代,并尝试取消分配部分内存块。@ustun:我也喜欢clang,但这有什么帮助?@Lucas我不确定,但clang static analyzer(不是编译器)有时有助于解决内存泄漏问题。这是真的,但是我以前提出过这一点,所以被资深的C程序员狠狠地瞪了一眼。这是公平的,因为如果你不整理这些内存,那么当它们发生时,你该如何发现真正的内存泄漏呢?这就像编译器中有50条警告,你忽略了它们,因为你知道它们“正常”。当警告51出现时,它只是在噪音中迷失了方向。为了清楚地结束讨论,在这个问题的上下文中,释放或不释放的问题根本不重要。OP特别询问如何正确释放已使用的空间,而不是他是否应该释放空间。:-)“不管它是否是更大的应用程序的一部分——exit()语义不会因此而改变……”——没有抓住要点;在实际应用程序中,exit可能会在很久以后调用。“手动调用free()不必要地占用了资源”--你到底在说什么?“也许op发布的只是更大应用程序的一个子集?”。。。“也许我是一个太空外星人。”——OP发布的内容实际上可能只是一个更大应用程序的子集,而你不可能是一个太空外星人。。。但如果你是一个,你就是一个粗鲁的人。谢谢你,你的回答澄清了我关于释放动态分配数组的误解。
void cleanUp(){
    int i = 0;
    int j = 0;

    for (i = 0; i < rowcnt; i++){
        free(rows[i]->columns);
    }
    free(rows); 
    exit(0);
}