2012-12-28 116 views
3

我的結構名爲Table,它包含一個名爲Object的結構數組。對象持有另一個指針Object。我希望有兩個方法 - 即(分別ObjectPTableP)釋放時,指針指向這些結構都給出了Table一個釋放的Object和一個:c - 正確釋放結構的內存

這是我目前幼稚的做法絕對不因爲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)); 
... 
} 
+0

有什麼警告的例子你看到了嗎? – prprcupofcoffee

+0

你能展示你怎麼分配它們嗎?通常刪除的對象應該涉及到'free'的多次調用,因爲構建必須使用'malloc' – simonc

+0

什麼是'top'?它是第一個元素嗎? –

回答

2

我不喜歡你ObjectPTableP符號;我打算用Object *Table *來明確指示。

從評論,你只關心刪除整個表;這很好,因爲它比刪除任意對象簡單得多。

我假設tableSize參數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()calloc()的原始分配。

+0

從你的例子中學到了很多,謝謝! – Tom

0

FreeTable()必須遍歷數組上的所有對象調用free()。

在嘗試任何處理內存管理的代碼之前,您應該先了解/瞭解計算機如何在低級作用域工作。

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); 
} 
+0

我通常不喜歡遞歸函數,但它在這裏是非常有意義的...假設沒有循環...但是如果循環是可能的,你也必須沒有obj->下一個 –

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); 
} 
+0

你很近,但我認爲你使用'FreeObjectChain()'的方式存在問題。麻煩的是,你會嘗試在'table-> linkedObjects'中分別釋放數組中的每個元素(這不是一個好主意)。我想你需要將'table-> linkedObjects [i] .next'傳遞給'FreeObjectChain()'來避免這個問題。 –

+0

我不確定我是否正確,但請注意我的'FreeObjectChain'從'obj-> next'開始,這也應該避免你提到的問題。 (你的建議可能看起來更自然) – Kos

+0

好的 - 是的;你是對的。這解決了這個問題。你沒事;我的評論是不相關/不準確的。 –