小型字典哈希实现问题:insert函数触发Segmentation fault
哈希表insert函数段错误问题排查
嘿,我看到你在给小型字典做哈希处理时,运行到insert()函数触发了Segmentation fault,而且已经怀疑和malloc()有关,咱们来揪出问题所在:
首先先把你的HASH.c代码贴出来方便分析:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <ctype.h> #include <string.h> typedef struct node { char* name; struct node* next; } node; node* first[26] = {NULL}; int hash(const char* buffer) { return tolower(buffer[0]) - 'a'; } void insert(int key, const char* buffer) { node* newptr = malloc(sizeof(node)); if (newptr == NULL) { return; } strcpy(newptr->name, buffer); newptr->next = NULL; if (first[key] == NULL) { first[key] = newptr; } else { node* predptr = first[key]; while (true) { if (predptr->next == NULL) { predptr->next = newptr; break; } predptr = predptr->next; } } }
问题根源
你只给node结构体本身分配了内存,但结构体里的char* name只是一个未初始化的指针——它没有指向任何有效的内存空间。当你调用strcpy(newptr->name, buffer)时,你试图把buffer里的字符串复制到一个随机的内存地址里,这直接触发了段错误(操作系统不允许访问非法内存)。
修复方案
你需要给name指针单独分配足够存储字符串的内存,这里有两种简单的实现方式:
方式一:使用strdup(推荐)
strdup会自动计算字符串长度、分配内存,然后完成复制,代码改动最小:
void insert(int key, const char* buffer) { node* newptr = malloc(sizeof(node)); if (newptr == NULL) { return; } // 替换原来的strcpy,用strdup分配内存并复制字符串 newptr->name = strdup(buffer); if (newptr->name == NULL) { // 别忘了检查strdup的分配结果 free(newptr); // 避免内存泄漏 return; } newptr->next = NULL; // 以下链表插入逻辑不变 if (first[key] == NULL) { first[key] = newptr; } else { node* predptr = first[key]; while (true) { if (predptr->next == NULL) { predptr->next = newptr; break; } predptr = predptr->next; } } }
方式二:手动分配内存
如果你不想用strdup(比如某些环境不支持),可以手动计算字符串长度再分配内存:
void insert(int key, const char* buffer) { node* newptr = malloc(sizeof(node)); if (newptr == NULL) { return; } // 计算字符串长度+1(存末尾的'\0') size_t str_len = strlen(buffer) + 1; newptr->name = malloc(str_len); if (newptr->name == NULL) { free(newptr); return; } strcpy(newptr->name, buffer); newptr->next = NULL; // 以下链表插入逻辑不变 if (first[key] == NULL) { first[key] = newptr; } else { node* predptr = first[key]; while (true) { if (predptr->next == NULL) { predptr->next = newptr; break; } predptr = predptr->next; } } }
额外提醒
后续销毁哈希表的时候,记得要先释放每个node里的name内存,再释放node本身,避免内存泄漏哦。
内容的提问来源于stack exchange,提问作者user13279908
相关产品推荐
相关产品推荐

