为啥哈希函数会给出分段错误?

Posted

技术标签:

【中文标题】为啥哈希函数会给出分段错误?【英文标题】:Why does the hash function give a segmentation fault?为什么哈希函数会给出分段错误? 【发布时间】:2021-04-27 17:12:39 【问题描述】:

我试图制作一个拼写检查程序,我首先必须将字典加载到内存中。为此,我尝试使用哈希表。当我对哈希表使用哈希函数时,程序显示分段错误。

// Implements a dictionary's functionality

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

#include "dictionary.h"

// Represents a node in a hash table
typedef struct node

    char word[LENGTH + 1];
    struct node *next;

node;

// Number of buckets in hash table
const unsigned int N = 6536;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)

    //TODO
    return false;


// Hashes word to a number
unsigned int hash(const char *word)         //Hashed using djb2

    unsigned long hash = 5381; 
    int c = 0;
   
    while (c == *word++)
    
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    
    return hash;


// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)

    char *str = NULL;
    FILE *dict = fopen(dictionary,"r");
    node *temp = NULL;
    if(dict == NULL)
    
        //printf("Error: \n", strerror(errno));
        return false;
    
    for(int i = 0; i < N; i++)
    
        table[i] = NULL;
    
    while(fscanf(dict, "%s", str) != 1)
    
        unsigned int key = hash(str);
        temp = malloc(sizeof(node));
        if(temp == NULL)
        
            return false;
        
        if(table[key] != NULL)
        
            temp->next = table[key]->next;
            strcpy(temp->word, str);
            table[key]->next = temp;
            free(temp);
        
        else
        
            table[key] = malloc(sizeof(node));
            table[key]->next = NULL;
            strcpy(table[key]->word, str);
        
    
    fclose(dict);
    printf("SUCCESS\n");
    return true;

调试器显示段。 unsigned int key = hash(str); 发生故障。我想知道如何解决这个问题。

【问题讨论】:

为什么没有人发过minimal reproducible example? 循环语句while (c == *word++) 闻起来很腥。你的意思是while (c = *word++)?否则,c 的值永远不会是零。 @AdrianMole 使用 while (c = *word++) 会导致编译器错误:dictionary.c:38:14: note: use '==' to turn this assignment into an equality comparison while (c = *word++) while(fscanf(dict, "%s", str) != 1) -- 我很确定你的意思是== 1 这里(“只要扫描一个单词成功......”) while 循环中使用赋值作为条件是允许的并且有时很有用:赋值产生一个值,即右侧的值,并将其评估为布尔值:0 表示假,其他一切都意味着真实。更常见的是将== 作为条件进行比较,并且在需要比较时使用 ans 赋值是很常见的。因此,编译器发出警告。您可以通过将赋值放在括号中来避免此警告:while ((c = *word++)) ... 【参考方案1】:

试试

char str[MAX_LEN];

而不是

char *str = NULL;

(在将MAX_LEN 定义为适合您的应用程序之后)。

正如 M Oehm 在评论中指出的那样,我认为您也可能错误地解释了 fscanf() 的返回值。

【讨论】:

在尝试存储字符串时声明字符数组和字符指针有区别吗? 当然有区别。该阵列已经存储了 MAX_LEN 附加字符。空指针没有附加内存并且不能被取消引用。尝试通过此指针存储数据将不起作用并且可能会崩溃。 @MelPradeep @M Oehm 说了什么;)。

以上是关于为啥哈希函数会给出分段错误?的主要内容,如果未能解决你的问题,请参考以下文章

对向量使用 Push Back 功能时的分段错误

为啥这个 AT&T 汇编代码会出现分段错误?

逐行读取文件然后哈希它们,在php中给出错误的输出

为啥将地址右移三位作为固定大小哈希表的哈希函数?

为啥这个程序在调用函数时会出现分段错误?

为啥不将哈希函数迭代 10,000,000 次? [复制]