【问题标题】:Segfault in simple hash table简单哈希表中的段错误
【发布时间】:2012-04-26 15:51:04
【问题描述】:

我正在尝试用 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;
}

【问题讨论】:

  • 您是否尝试使用调试器来调试您的程序?
  • key &gt;= 0 ? key : -key 怎么了???

标签: c segmentation-fault hashtable


【解决方案1】:

至少有一个问题:

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-th 元素。

【讨论】:

  • 哇,我永远不会想到这一点。我改变了它,它完美地工作!所以在指针算术中,如果其中一个值不是指针本身,C 会乘以指针的大小吗?
  • @Daniel 在指针算术中,它将乘以指向类型的大小。
  • 语法return &amp;table[key]; 不太容易出错,并且可能更具可读性。
【解决方案2】:

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

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; 
}

【讨论】:

    猜你喜欢
    • 2017-12-01
    • 2013-12-25
    • 2016-03-03
    • 1970-01-01
    • 2012-04-23
    • 2018-10-29
    • 2013-06-12
    • 2016-07-14
    相关资源
    最近更新 更多