3

我的名为 的结构Table包含一个名为 的结构的数组Object。Object 持有指向另一个的指针Object。我想做两种方法——一种释放 an Object,另一种释放 aTable当指向这些结构的指针时(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

4 回答 4

2

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

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

图形

那么删除的方法是:

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);
}
于 2012-12-28T22:20:36.240 回答
2

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

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

我假设tableSize参数 toCreateTable()存储在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()。请记住, arealloc()可以更改先前分配的地址,但realloc()必须释放 from 的值而不是来自malloc()or的原始分配calloc()

于 2012-12-28T22:18:39.813 回答
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);
}
于 2012-12-28T22:15:38.397 回答
0

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

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

于 2012-12-28T22:09:30.127 回答