Segfault在简单的哈希表中

时间:2012-04-14 16:11:11

标签: c segmentation-fault hashtable

我正在尝试在C中编写一个简单的哈希表,并且在使用显示为main()的代码进行测试时,我得到了一个非常奇怪的段错误。

设计:我有一个哈希表,其底层数组大小为10,000。我持有一个双指针指向struct node_t(或node)指针数组的开头。当我想在哈希表中put()时,我会检查相应位置的node元素是否为NULL。如果是,我创建一个新节点来填充该点,否则,如果存在冲突,我会从冲突节点构建链接列表。

情景:main()中,我正在尝试将put()数字3328放入哈希表中。相反,程序段错误。这对我没有意义,因为之前的put()工作正常,你可以清楚地看到我将所有初始指针设置为NULL。据我所知,引用哈希表位置3328的指针没有设置为NULL,因为当我在put()函数中取消引用它时,就是它的段错误。我的主要功能看起来应该将所有指针设置为NULL,尽管...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int TABLE_SIZE = 10000;

typedef struct node_t {
    int key;
    int value;
    struct node_t* next;
} node;

node** table;

inline node** get_node_address(int key) {
    key = (key > -key ? key : -key) % TABLE_SIZE;
    return (node**) (table + key * sizeof(node*)); 
}

inline node* new_node(int key, int value) {
    node* n = malloc(sizeof(node));
    n->key = key;
    n->value = value;
    n->next = NULL;
    return n;
}

void put(int key, int value) {
    node** n = (node**) get_node_address(key);
    node* iterator = (node*) *n;

    if (*n == NULL) {
        *n = new_node(key, value);
    } else {
        while (iterator->next != NULL)
            iterator = iterator->next;

        iterator->next = new_node(key, value);
    }
}

int* get(int key) {
    node* iterator = (node*) *get_node_address(key);

    while (iterator != NULL && iterator->key != key) {
        iterator = iterator->next;
    }

    if (iterator == NULL)
        return NULL;
    else
        return &(iterator->value); 
}

int main() {
    printf("Starting..\n");

    int i;
    table = malloc(sizeof(node*) * TABLE_SIZE);
    memset(table, 0, sizeof(node*) * TABLE_SIZE);

    for (i = 0; i < TABLE_SIZE; i++) {
        table[i] = NULL;
        printf("setting %x\n", &table[i]);
    }

    printf("before bad: %x\n", *get_node_address(3327));
    printf("bad address: %x\n", *get_node_address(3328));
    printf("last address: %x\n", table + sizeof(node*) * TABLE_SIZE);

    printf("Hashing...\n");

    put(3328, 3338);
    printf("%d", *get(3328));

    return 0;
}

2 个答案:

答案 0 :(得分:4)

至少有一个问题:

inline node** get_node_address(int key) {
      key = (key > -key ? key : -key) % TABLE_SIZE;
      return (node**) (table + key * sizeof(node*)); /* <---- */
}

你不能乘以key。由于指针算法在C中的工作方式,table + key会产生key个元素。

答案 1 :(得分:0)

上面的代码可以简化很多:

void put(int key, int value) {
  node **n = get_node_address(key);


  for (n = get_node_address(key); *n; n = &(*n)->next) {;}

  if(*n == NULL)
    *n = new_node(key, value);

}

int* get(int key) {
  node  **n;

  for (n = get_node_address(key); *n; n = &(*n)->next) {
    if (n->key == key) break;
    }

  if(*n == NULL)
    return NULL;
  else
    return &(*n)->value; 
}