c - 正确释放结构的内存

时间:2012-12-28 22:01:59

标签: c memory

我的名为Table的结构包含一个名为Object的结构数组。 Object包含指向另一个Object的指针。我想创建两个方法 - 一个释放Object,另一个释放Table时指向这些结构的指针(分别为ObjectPTableP):

这是我目前的天真实现,由于valgrid在整个地方吐出警告(我真的很想从Java中获取c),这绝对不起作用:

/*
 * Represents a linked list containing a key value
 */
typedef struct Object {
    void *key;
    struct Object *top;
    struct Object *next;
    Boolean originalCell;
} Object;

/*
 * Represents a table that stores keys based on a given object's hash
 */
typedef struct Table{
    Object *linkedObjects;
    size_t size, originalSize;
    HashFcn hfun;
    PrintFcn pfun;
    ComparisonFcn fcomp;
    Boolean wasDuplicated;
} Table;

void FreeObject(ObjectP object)
{
    free(object);
}

void FreeTable(TableP table)
{
    free(table);
}

我应该如何正确地释放这些结构?

编辑:

这是我分配变量的方式:

ObjectP CreateObject(void *key)
{
struct Object *object = (struct Object*) malloc(sizeof(struct Object));
...
}

TableP CreateTable(size_t tableSize, HashFcn hfun, PrintFcn pfun, ComparisonFcn fcomp)
{
    struct Table *table = malloc(sizeof(Table));

    if (table==NULL)
    {
        ReportError(MEM_OUT);
        return NULL;
    }

    table->linkedObjects = NULL;
    table->linkedObjects  = malloc(tableSize * sizeof(Object));
...
}

4 个答案:

答案 0 :(得分:2)

我不喜欢你的ObjectPTableP符号;我将使用Object *Table *明确指出。

从评论中,您只关心删除整个表格;这很好,因为它比删除任意对象简单得多。

我假设tableSize的{​​{1}}参数存储在CreateTable()中。

table->size

static Object *FreeObject(Object *obj) { Object *next = 0; if (obj != 0) { free(obj->key); // If you allocated this next = obj->next; free(obj); } return(next); } void FreeTable(Table *tab) { if (tab != 0) { for (size_t i = 0; i < tab->size; i++) { Object *next = tab->linkedObjects[i].next; while ((next = FreeObject(next)) != 0) ; free(tab->linkedObjects[i].key); // If you allocated this } free(tab->linkedObjects); free(tab); } } 函数是静态的,因为它仅供FreeObject()使用。它删除密钥,假设在分配对象时分配了密钥;它捕获指向列表中下一个项目的指针(可能是空指针),释放对象本身,并返回指向下一个项目的指针。

FreeTable()函数使用FreeTable()函数释放挂起在名为FreeObject()的数组中分配的对象的链接对象列表中的所有对象,然后删除对象数组,然后删除表。

释放内存时的关键是确保每个分配都有一个空闲,每个分配只有一个空闲。传递给linkedObjects的值必须是free()malloc()calloc()的值。请注意,realloc()可以更改以前分配的地址,但必须释放realloc()的值,而不是realloc()malloc()的原始分配。

答案 1 :(得分:2)

为了删除整个表(以及对象),您需要遍历对象图并为通过malloc分配的每个块调用free(),即一个Object或其中一个数组

我理解您的对象图如下所示:

Graph

然后删除的方法是:

void FreeObjectChain(Object* obj) {
    Object* curr = obj->next;
    while (curr) {
        Object* tmp = curr;
        curr = tmp->next;
        free(tmp);
    }
}

void FreeTable(Table* table) {
    for (int i=0; i<table->size; ++i) {
        FreeObjectChain( &(table->linkedObjects[i]) );
        // or simply FreeObjectChain( table->linkedObjects + i );
    }
    free(table->linkedObjects);
    free(table);
}

答案 2 :(得分:1)

我会尝试做类似的事情:

void freeObject(Object* obj) {
    if (obj->next != NULL) {
        freeObject(obj->next);
    }
    if (obj->key != NULL) {
        free(obj->key);
    }   
    free(obj);
}

void freeTable(Table* table) {
     for (int i=0; i<table->size; ++i) {
         freeObject(&(table->linkedObjects[i]));
     }
     freeObject(table->linkedObjects);
     free(table);
}

答案 3 :(得分:0)

FreeTable()必须遍历数组并在所有对象上调用free()。

在尝试任何处理内存管理的代码之前,您应首先了解/了解计算机在低级别范围内的工作方式。