C语言实现简易字典时出现Segfault段错误求助
问题:C语言简易字典实现出现段错误
我参考某Stack Overflow帖子实现简易字典,但对代码做了修改,调试时出现段错误,求帮助。
字典实现代码
/* String utility for duplication */ char *strdup(char *s) /* make a duplicate of s */ { char *p; p = (char *) malloc(strlen(s)+1); /* +1 for ’\0’ */ if (p != NULL) strcpy(p, s); return p; } struct nlist { struct nlist *next; char *name; char *defn; }; #define HASHSIZE 101 struct Dict { struct nlist *hashtab[HASHSIZE]; }; /* hash: form hash value for string s */ unsigned hash(char *s) { unsigned hashval; for (hashval = 0; *s != '\0'; s++) hashval = *s + 31 * hashval; return hashval % HASHSIZE; } /* lookup: look for s in hashtab */ struct nlist *lookup(struct Dict *d, char *s) { struct nlist *np; for (np = d->hashtab[hash(s)]; np != NULL; np = np->next) if (strcmp(s, np->name) == 0) return np; /* found */ return NULL; /* not found */ } struct nlist *insert(struct Dict *d, char *name, char *defn) { struct nlist *np; unsigned hashval; if ((np = lookup(d, name)) == NULL) { /* not found */ np = (struct nlist *) malloc(sizeof(*np)); if (np == NULL || (np->name = strdup(name)) == NULL) return NULL; hashval = hash(name); np->next = d->hashtab[hashval]; d->hashtab[hashval] = np; } else /* already there */ free((void *) np->defn); /*free previous defn */ if ((np->defn = strdup(defn)) == NULL) return NULL; return np; }
测试代码
int main() { struct Dict *dtest = (struct Dict*)malloc(sizeof(struct Dict)); insert(dtest, "hello", "world"); // Look up a definition by name struct nlist *result = lookup(dtest, "hello"); if (result != NULL) { printf("Definition for 'hello': %s\n", result->defn); } else { printf("'hello' is not found in the dictionary.\n"); } return 0; }
错误信息
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ff6bc661626 in lookup (d=0x220924616e0, s=0x7ff6bc673006 "hello") at dict.c:40
40 if (strcmp(s, np->name) == 0)
问题分析与解决
段错误出在lookup函数的strcmp(s, np->name)行,核心原因是**Dict结构体的hashtab数组未初始化**。
用malloc分配struct Dict内存时,只会预留空间,不会将内存内容初始化为0。这意味着dtest->hashtab里的所有指针都是随机的垃圾值。当insert调用lookup时,d->hashtab[hash(s)]会取到一个无效的随机地址,np指向该地址后,访问np->name就会触发段错误。
解决方法
有两种可靠的初始化方式:
- 用
calloc替代malloccalloc会自动将分配的内存初始化为0,直接修改main中的内存分配代码:
struct Dict *dtest = (struct Dict*)calloc(1, sizeof(struct Dict));
- 手动初始化哈希表指针
如果坚持使用malloc,需要手动将hashtab的每个元素设为NULL:
struct Dict *dtest = (struct Dict*)malloc(sizeof(struct Dict)); // 初始化哈希表所有指针为NULL for (int i = 0; i < HASHSIZE; i++) { dtest->hashtab[i] = NULL; }
额外优化建议
- 自定义的
strdup函数未处理s为NULL的情况,传入空指针会导致strlen崩溃,建议增加判断:
char *strdup(char *s) { if (s == NULL) return NULL; char *p = (char *) malloc(strlen(s)+1); if (p != NULL) strcpy(p, s); return p; }
- 程序结束时记得遍历字典释放所有节点的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者syaheer-altaf
相关产品推荐
相关产品推荐

