3

という名前Tableの構造体は、という名前の構造体の配列を保持していObjectます。オブジェクトは別のへのポインタを保持しますObject。2つのメソッドを作成したいと思います。1つはanを解放し、もう1つはこれらの構造体へのポインターが与えられObjectたときにaを解放します(それぞれ)。TableObjectPTableP

これは私の現在の素朴な実装であり、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を介して割り当てられた各ブロック、つまりこれらの1つObjectまたは1つの配列を呼び出す必要があります。

オブジェクトグラフは次のようになっていると思います。

グラフ

次に、削除する方法は次のとおりです。

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 *ます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()。オブジェクトが割り当てられたときにキーが割り当てられたと想定して、キーを削除します。リスト内の次の項目へのポインター(nullポインターの場合もあります)をキャプチャし、オブジェクト自体を解放して、次の項目へのポインターを返します。

このFreeTable()関数は、この関数を使用FreeObject()して、という名前の配列に割り当てられたオブジェクトにぶら下がっているリンクされたオブジェクトリスト内のすべてのオブジェクトを解放し、linkedObjects次にオブジェクトの配列を削除してから、テーブルを削除します。

メモリを解放する際の重要なことは、割り当てごとに1つだけ空きがあり、割り当てごとに1つだけ空きがあることを確認することです。に渡される値は、、またはからfree()の値である必要があります。aは前の割り当てのアドレスを変更できますが、またはからの元の割り当てではなく、からの値を解放する必要があることに注意してください。malloc()calloc()realloc()realloc()realloc()malloc()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 に答える