【发布时间】:2013-01-17 19:32:10
【问题描述】:
我正在用 C 语言编写一个简单的程序,它根据在哈希表中查找单词的字谜来查找它们。我所拥有的是一个哈希表数组,其中单词按其长度索引,并通过其字母的总和在其中进行哈希处理,例如a = 1,b = 2,等等。
我仍然熟悉 C 中的动态内存管理,所以这个问题可能很简单,但我有一个函数可以为每个哈希表(及其内部数据)分配和取消分配内存。
我最初使用单个哈希表编写此程序,通过 valgrind 运行程序后,我发现内存已正确释放并且没有泄漏。然而,当扩展程序以使用哈希表数组时,valgrind 开始发现可能的泄漏(尽管它报告它们仍然可以访问)。我对为什么在哈希表数组中没有正确释放内存感到困惑,尽管数组中的每个哈希表都是通过最初使用的 deallocate 函数运行的。
完整代码Full Code
typedef struct Bucket Bucket;
typedef struct HashTable HashTable;
struct Bucket {
char* data;
Bucket *next;
};
struct HashTable {
int size;
Bucket **buckets;
};
int main(int argc, char const *argv[])
{
// Allocate memory for array of hash tables
HashTable** hash_array = (HashTable**) malloc(sizeof(HashTable*) * WORD_SIZE);
for(i = 0; i < WORD_SIZE; i++) {
hash_alloc(&hash_array[i], BUCKET_COUNT);
}
// Main logic here...
// Free memory
for(i = 0; i < WORD_SIZE; i++) {
hash_dealloc(hash_array[i]);
}
free(hash_array);
return 0;
}
哈希表分配函数
void hash_alloc(HashTable** a, unsigned int size) {
*a = (HashTable*) malloc(sizeof(HashTable));
(*a)->buckets = (Bucket**) malloc(sizeof(Bucket*) * size);
(*a)->size = size;
}
哈希表释放函数
void hash_dealloc(HashTable* a) {
int i;
Bucket* current, *temp;
for(i = 0; i < a->size; i++) {
current = a->buckets[i];
while(current != NULL) {
temp = current;
free(temp->data);
current = current->next;
free(temp);
}
free(current);
}
free(a->buckets);
free(a);
}
加入哈希表函数
void add_to_hash_array(HashTable** a, char* data) {
// Removed some other logic for readability...
replace_str(data, "\n", "\0");
newNode->data = strdup(data);
newNode->next = currentTable->buckets[index];
currentTable->buckets[index] = newNode;
} else {
return;
}
}
Valgrind 输出
==39817== 261,120 bytes in 128 blocks are still reachable in loss record 5 of 7
==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==39817== by 0x400A38: hash_alloc (main.c:73)
==39817== by 0x4008B0: main (main.c:39)
==39817==
==39817== 286,936 bytes in 31,553 blocks are still reachable in loss record 6 of 7
==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==39817== by 0x4EBAD71: strdup (strdup.c:43)
==39817== by 0x400D4D: add_to_hash_array (main.c:141)
==39817== by 0x400914: main (main.c:51)
==39817==
==39817== 504,848 bytes in 31,553 blocks are still reachable in loss record 7 of 7
==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==39817== by 0x400D16: add_to_hash_array (main.c:136)
==39817== by 0x400914: main (main.c:51)
【问题讨论】:
-
能否请您重写代码而不使用多余的强制转换等,使其更具可读性?
-
我已经编辑了一些不相关的逻辑,并留下了对问题很重要的分配和释放。希望对您有所帮助。
-
我们可以看到
HashTable和Bucket声明吗? -
当然。我刚刚编辑了它们。
-
HashTable** hash_array = (HashTable**) malloc(sizeof(HashTable*) * WORD_SIZE);为什么不使用Hash_alloc()函数呢?
标签: c memory-management memory-leaks valgrind