C语言中使用链表解决冲突的哈希表内存分配问题求助
问题分析与修复方案
以下是代码中存在的可直接导致运行异常的错误:
- 新创建的哈希项未接入哈希表结构:你在
create_item函数中遍历完对应索引的链表尾部后,仅给新节点设置了prev指针,没有将新节点挂载到链表上。如果当前索引的链表为空(prev为NULL),需要将table->items[index]指向新节点;如果链表不为空,需要将前序节点的next指针指向新节点。否则新节点完全脱离哈希表的管理,不仅后续访问不到,还会造成内存泄漏。 - 打印函数存在内存操作错误:
print_table中你为迭代器指针额外申请了内存,随后直接将迭代器赋值为链表节点的地址,刚申请的内存直接泄漏;遍历结束后迭代器已经为NULL,此时的free操作也属于无意义的冗余代码。迭代器仅作为遍历用的指针变量,不需要单独分配内存。 - 存在缓冲区溢出风险:当前你固定分配200字节存储key和value,若传入的字符串长度超过199会触发缓冲区溢出,建议根据实际字符串长度动态分配内存。
- 冗余初始化逻辑:
create_table中你用calloc申请的items数组已经默认初始化为全0,所有元素指针本身就是NULL,后续的循环赋值操作属于冗余代码,不影响运行但无意义。
修正后完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define CAPACITY 50000 unsigned long hash(char *str) { unsigned long int stringsum = 0; for(; *str != '\0'; str++) { stringsum += *str; } return stringsum % CAPACITY; } typedef struct item { char *value; char *key; struct item *next; struct item *prev; } ht_item; typedef struct hashtable { ht_item **items; int dim; int count; } HashTable; HashTable* create_table(int size); // 函数名调整为更贴合语义的insert_item,原create_item语义不准确 void insert_item(HashTable *table, char *value, char *key); void print_table(HashTable* table, int dim); int main(void) { HashTable *table = create_table(CAPACITY); insert_item(table, "Giuseppe", "Nome"); print_table(table, CAPACITY); // 实际使用时记得补充哈希表销毁逻辑,释放所有节点内存避免泄漏 return 0; } void insert_item(HashTable *table, char *value, char *key) { unsigned long index = hash(key); printf("当前key的哈希索引:%lu\n", index); ht_item *_iterator; ht_item *prev; for(_iterator = table->items[index], prev = NULL; _iterator != NULL; prev = _iterator, _iterator = _iterator->next); _iterator = (ht_item*)malloc(sizeof(ht_item)); // 按实际字符串长度分配内存,避免溢出 _iterator->key = (char*)malloc(strlen(key) + 1); _iterator->value = (char*)malloc(strlen(value) + 1); strcpy(_iterator->key, key); strcpy(_iterator->value, value); _iterator->next = NULL; _iterator->prev = prev; // 新增:把新节点挂载到链表上 if (prev == NULL) { table->items[index] = _iterator; } else { prev->next = _iterator; } table->count++; } HashTable* create_table(int size) { HashTable *table = (HashTable*)malloc(sizeof(HashTable)); table->dim = size; table->count = 0; table->items = (ht_item**)calloc(size, sizeof(ht_item*)); return table; } void print_table(HashTable* table, int dim) { for(int i = 0; i < dim; i++) { if(table->items[i] != NULL) { // 迭代器不需要分配内存,直接指向链表头即可 ht_item *_iterator = table->items[i]; for(; _iterator != NULL; _iterator = _iterator->next) { printf("索引:%d\tKey: %s\tValue: %s\n", i, _iterator->key, _iterator->value); } } } }
内容的提问来源于stack exchange,提问作者aocLEL
相关产品推荐
相关产品推荐

