这是我的代码:
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "dictionary.h"
// Maximum length for a word
#define LENGTH 45
//define struct node
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
//hash function
unsigned int hash(const char word[LENGTH + 1])
{
int x = atoi(&word[0]);
int y;
if(isupper(word[0]))
{
y = (x + 13) % 26;
}
if(islower(word[0]))
{
y = (x + 7) % 26;
}
if(isalpha(word[0]) == 0)
{
return 0;
}
return y;
}
//make a hash table of linked lists
node* hash_table[26];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
node *head = hash_table[hash(word)];
node *cursor = head;
while (cursor != NULL)
{
if (strcasecmp(word, cursor->word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
char word[LENGTH + 1];
FILE *dictionary_file = fopen(dictionary, "r");
if (dictionary_file == NULL)
{
unload ();
return false;
}
while (fscanf(dictionary_file, "%s", word) != EOF)
{
//allocate memory for node
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
//insert node into linked list
int index = hash(word);
node *head = hash_table[hash(word)];
//place word in node
strcpy(new_node->word, word);
//connect nodes
new_node->next = head;
hash_table[index] = new_node;
}
fclose(dictionary_file);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
int sum = 0;
if (&load)
{
char word[LENGTH + 1];
const char *dictionary;
FILE *dictionary_file = fopen(dictionary, "r");
while (fscanf(dictionary_file, "%s", word) != EOF)
{
sum++;
}
}
return sum;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
char word[LENGTH + 1];
node *head = hash_table[hash(word)];
node *cursor = head;
while (cursor != NULL)
{
node *temp = cursor;
cursor = cursor->next;
free(temp);
}
if (cursor == NULL)
{
return true;
}
else
{
return false;
}
}
当我通过GDB运行它时,我收到以下消息,指示分段错误:
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x7ffff728d760 <main_arena>, bytes=56) at malloc.c:3777
3777 malloc.c: No such file or directory.
这是我键入“ where”时的GDB响应:
#0 _int_malloc (av=0x7ffff728d760 <main_arena>, bytes=56) at malloc.c:3777
#1 0x00007ffff6f4dae0 in __GI___libc_malloc (bytes=56) at malloc.c:2893
#2 0x0000000000422abf in load (dictionary=0x382e332d6e696168 <error: Cannot access memory at address 0x382e332d6e696168>)
at dictionary.c:66
#3 0x722d72656c69706d in ?? ()
#4 0x61732f62696c2f74 in ?? ()
#5 0x5f72657a6974696e in ?? ()
#6 0x732f6e6f6d6d6f63 in ?? ()
#7 0x72657a6974696e61 in ?? ()
#8 0x632e7367616c665f in ?? ()
#9 0x6165720000000063 in ?? ()
#10 0x0063632e31720064 in ?? ()
#11 0x2828000000000000 in ?? ()
#12 0x5f76625f706d7421 in ?? ()
#13 0x287469427465672e in ?? ()
#14 0x6c00292929786469 in ?? ()
#15 0x6c6f6f742d6d766c in ?? ()
有人知道为什么会出现分段错误吗?当我通过valgrind运行程序时,系统指示没有内存泄漏。有谁知道如何解决这个问题?
答案 0 :(得分:0)
load()
函数中存在多个问题,但是我不确定它们是否导致分段错误。
您正在呼叫hash(new_node->word)
,然后再从word
复制到new_node->word
。您应该改为对word
进行哈希处理。
您实际上从未真正将新节点放入哈希表。将head
链接到旧头之后,您需要将其设置为// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
char word[LENGTH + 1];
FILE *dictionary_file = fopen(dictionary, "r");
if (dictionary_file == NULL)
{
unload ();
return false;
}
while (fscanf(dictionary_file, "%s", word) != EOF)
{
//allocate memory for node
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
//insert node into linked list
int hashcode = hash(word);
node *head = hash_table[hashcode];
//place word in node
strcpy(new_node->word, word);
//connect nodes
new_node->next = head;
hash_table[hashcode] = new_node;
}
fclose(dictionary_file);
return true;
}
,但是哈希表仍指向旧头。
更新的代码:
valgrind
我在您发布的代码中没有看到任何会引起分段错误的内容,因此您可能在未包含的某些其他代码中具有未定义的行为。使用dendy <- lapply(1:100, function1)
之类的工具来查找它。
答案 1 :(得分:0)
关于:
const char *dictionary;
FILE *dictionary_file = fopen(dictionary, "r");
(可能是段故障的原因)
指针dictionary
在传递给fopen()
之前未初始化
因此,代码试图从内存中的某个“随机”位置读取一定数量的“随机”字节(直到遇到NUL字节),以尝试获取要打开的文件的名称。
OT:在调用fopen()
之类的C库函数时,请始终在调用后检查是否有任何错误。
编译时,请始终启用警告,然后修复这些警告。 (对于gcc
,至少使用-Wall -Wextra -Wconversion -pedantic -std=gnu11
)