You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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就会触发段错误。

解决方法

有两种可靠的初始化方式:

  1. 用calloc替代malloc
    calloc会自动将分配的内存初始化为0,直接修改main中的内存分配代码:
struct Dict *dtest = (struct Dict*)calloc(1, sizeof(struct Dict));
  1. 手动初始化哈希表指针
    如果坚持使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 03:33:39