实现基于链表的哈希表时触发Segmentation fault问题求助
错误排查与修复方案
直接触发段错误的核心原因
add方法插入新节点后,错误执行了delete newNode:你刚刚将动态申请的新节点挂载到链表上,立刻就释放了该节点的内存,导致链表中存储的是野指针。后续print方法访问这块已经被回收的内存时,直接触发段错误。
其他潜在问题
hasher方法未做空字符串校验:如果传入空字符串,调用x[0]会发生数组越界,触发未定义行为。print方法未做空指针校验:如果对应哈希槽的链表没有对应节点,直接访问hashMap[hasher(key)].next->key会访问空指针,触发段错误。- 析构函数存在内存泄漏:当前仅释放了哈希数组本身,每个槽位链表上动态申请的节点都未被释放。
- 未禁用默认拷贝构造/拷贝赋值:默认的浅拷贝逻辑会导致两个哈希表对象指向同一块内存,析构时重复释放触发崩溃。
修正后的完整代码
#include <iostream> #include <string> class HashTable { public: HashTable() : hashMap{ new Node[10] } { for (int i = 0; i < 10; i++) { hashMap[i].next = nullptr; } } // 禁用拷贝构造和拷贝赋值,避免浅拷贝问题 HashTable(const HashTable&) = delete; HashTable& operator=(const HashTable&) = delete; ~HashTable() { // 先释放每个链表的节点 for (int i = 0; i < 10; i++) { Node* current = hashMap[i].next; while (current != nullptr) { Node* temp = current; current = current->next; delete temp; } } // 再释放哈希数组 delete[] hashMap; } unsigned int hasher(const std::string& x) { // 空字符串兜底处理 if (x.empty()) return 0; return x[0] % 10; } void add(const std::string& key) { Node* newNode = new Node; newNode->key = key; newNode->next = nullptr; unsigned int idx = hasher(key); if (hashMap[idx].next == nullptr) { hashMap[idx].next = newNode; } else { Node* current = hashMap[idx].next; while (current->next != nullptr) { current = current->next; } current->next = newNode; } // 移除错误的delete newNode操作 } void print(const std::string& key) { unsigned int idx = hasher(key); if (hashMap[idx].next == nullptr) { std::cout << "key not found" << std::endl; return; } std::cout << hashMap[idx].next->key << std::endl; } private: struct Node { std::string key; Node* next; }; Node* hashMap; }; int main() { HashTable ht; ht.add("Hello"); ht.print("Hello"); }
内容的提问来源于stack exchange,提问作者Steven
相关产品推荐
相关产品推荐

