在哈希表中安装键值时出现分段错误

问题描述

编辑:我已经更新了初始化函数代码已更新)以使用malloc,并且分段错误消失了。但是,我现在没有从打印表功能获得任何输出。 根据建议进一步更新了代码。看来现在可以使用。

我一直在关注K&R(C的初学者),并尝试使用第6.7节中的示例编写哈希表(进行了少量修改

代码在下面-

#include <stdio.h>
#include <string.h>
#include "hashtable.h"

#define HASHSIZE 101


listptr * init_table()
{
    listptr *hashtab = (listptr *) calloc(HASHSIZE,sizeof(*hashtab));
    return hashtab;
}

unsigned hash (char *s)
{
    unsigned hashval;

    for (hashval=0; *s != '\0'; s++)
        hashval = *s + 31 * hashval;

    return hashval % HASHSIZE;
}

listptr lookup (listptr * hashtab,char *s)
{
    listptr np;

    for (np = hashtab[hash(s)]; np!=NULL; np = np->next)
        if (strcmp(s,np->name) == 0)
            return np;
    return NULL;
}

listptr install(listptr * hashtab,char *name,char * defn)
{
    listptr np;

    unsigned hashval;

    if((np = lookup(hashtab,name)) == NULL) {
        np = (listptr) malloc(sizeof(*np));
        if (np==NULL || (np->name = strdup(name))==NULL)
            return NULL;

        hashval = hash(name);
        np->next = hashtab[hashval];
        hashtab[hashval] = np;
    }
    else
    {
        free((void*) np->defn);
    }
    if ((np->defn = strdup(defn)) == NULL)
        return NULL;

    return np;
}

void printtable(listptr * table,int len)
{
    listptr p;
    int i =0;
    while (i < len) {
        if (table[i] != NULL) {
            for (p = table[i];p!=NULL;p=p->next) {
                printf("%s\t%s\n",p->name,p->defn);
            }
        }
        i++;
    }
}

hashtable.h包含-

#ifndef HDR
#define HDR

#include <stdlib.h>

typedef struct nlist *listptr;

typedef struct nlist {
    listptr next;
    char *name;
    char *defn;
} Hashtablebucket;

listptr * init_table();
listptr lookup(listptr *,char *);
listptr install (listptr *,char *,char *);
void printtable(listptr *,int );

#endif

在main.c中,我有-

#include <stdio.h>
#include <string.h>
#include "hashtable.h"

int main()
{
    listptr * table = init_table();


    install(table,"key1","value1");
    install(table,"key2","value2");
    install(table,"key3","value3");

    printtable(table,101);

    return 0;
}

这会导致分段错误,并且我不知道这是怎么回事,因为哈希表具有101个空间元素。

在调试问题上会提供帮助...

编辑:使用以上代码,根本没有输出。有人可以帮忙调试吗?

预先感谢

解决方法

原始K&R代码采用全局表。在您的情况下,您尝试在本地分配它,但是您不能返回指向本地变量的指针(可以,但是行为未定义)。取而代之的是,您需要使用malloc /或更佳的分配calloc来分配内存,在这种情况下:

listptr * init_table()
{
    listptr *table = calloc(HASHSIZE,sizeof *table);
    return table;
}

最好为哈希表创建一个 struct ,这样您就可以拥有不同大小的表:

struct hashtable {
    size_t n_slots;
    listptr *slots;
};

struct hashtable *init_table(size_t n_slots) {
    struct hashtable *tbl = malloc(sizeof *tbl);
    tbl->n_slots = n_slots;
    tbl->slots = calloc(n_slots,sizeof *(tbl->slots));
    return tbl;
}

对于hash函数,最好保留它,使其始终返回unsigned int(或size_t!),并在该函数之外进行取模。另外,char可以签名或不签名;您很可能想使用unsigned char

size_t hash (char *s)
{
    size_t hashval;

    for (hashval=0; *s != '\0'; s++)
        hashval = *(unsigned char*)s + 31 * hashval;

    return hashval;
}

hashval = hash(name) % tbl->n_slots;