ハッシュテーブルを作成しましたが、基本的には次の 2 つの構造で構成されています。
typedef struct dictEntry {
void *key;
void *value;
struct dictEntry *next;
} dictEntry;
typedef struct dict {
dictEntry **table;
unsigned long size;
unsigned long items;
} dict;
dict.table
格納されたすべてのキーと値のペアを含む多次元配列であり、これもリンク リストです。
ハッシュテーブルの半分がいっぱいになった場合は、サイズを 2 倍にして再ハッシュすることで拡張します。
dict *_dictRehash(dict *d) {
int i;
dict *_d;
dictEntry *dit;
_d = dictCreate(d->size * 2);
for (i = 0; i < d->size; i++) {
for (dit = d->table[i]; dit != NULL; dit = dit->next) {
_dictAddRaw(_d, dit);
}
}
/* FIXME memory leak because the old dict can never be freed */
free(d); // seg fault
return _d;
}
上記の関数は、古いハッシュ テーブルからのポインターを使用し、新しく作成されたハッシュ テーブルに格納します。古いものを解放するとdict d
、セグメンテーション違反が発生します。
キーと値のペアにメモリを再度割り当てることなく、古いハッシュテーブル構造体を解放するにはどうすればよいですか?
完全を期すために編集:
dict *dictCreate(unsigned long size) {
dict *d;
d = malloc(sizeof(dict));
d->size = size;
d->items = 0;
d->table = calloc(size, sizeof(dictEntry*));
return d;
}
void dictAdd(dict *d, void *key, void *value) {
dictEntry *entry;
entry = malloc(sizeof *entry);
entry->key = key;
entry->value = value;
entry->next = '\0';
if ((((float)d->items) / d->size) > 0.5) d = _dictRehash(d);
_dictAddRaw(d, entry);
}
void _dictAddRaw(dict *d, dictEntry *entry) {
int index = (hash(entry->key) & (d->size - 1));
if (d->table[index]) {
dictEntry *next, *prev;
for (next = d->table[index]; next != NULL; next = next->next) {
prev = next;
}
prev->next = entry;
} else {
d->table[index] = entry;
}
d->items++;
}