C 分段错误 malloc.c:没有这样的文件或目录

问题描述 投票:0回答:3

这是我的代码:

// 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运行程序时,系统提示没有内存泄漏。有人知道如何解决这个问题吗?

c cs50
3个回答
1
投票

关于:

const char *dictionary;
FILE *dictionary_file = fopen(dictionary, "r");

(可能是seg错误的原因)

指针

dictionary
在传递给
fopen()

之前未初始化

因此代码尝试从内存中的某个“随机”位置读取一些“随机”字节数(直到遇到 NUL 字节),以尝试获取要打开的文件的名称。

OT:调用 C 库函数(如

fopen()
)时,请始终在调用后检查是否有任何错误。

编译时,始终启用警告,然后修复这些警告。 (对于

gcc
,至少使用:
-Wall -Wextra -Wconversion -pedantic -std=gnu11


0
投票

load()
函数中存在几个问题,但我不确定它们是造成分段错误的原因。

  1. 您在从

    hash(new_node->word)
    复制到
    word
    之前先调用
    new_node->word
    。您应该改为散列
    word

  2. 您实际上从未将新节点放入哈希表中。在将新节点链接到旧头后,您将

    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
之类的工具来帮助找到它。


0
投票

回答这个问题可能有点晚了,但我也面临着类似的用途(在 x86 汇编中编码时),所以我认为我的学习可能会有所帮助。

有人知道为什么会出现分段错误吗?

因此,当您需要在堆上分配一些内存时(比方说

12 bytes
),x86 指令如下所示:

movl $12, %rdi       # @first_argument: number of bytes to allocate
call malloc          # returns the start address of memory in %rax 

但是,根据 C 调用约定,在

call
指令期间,
%rsp
(堆栈指针)应该是
16
的倍数。如果不是这种情况,则会导致错误

malloc/malloc.c no such file or directory exists

此错误的一个可能来源可能是为调整局部变量的空间而进行的堆栈指针调整:

pushq %rbp
movq %rsp, %rbp
subq $12, %rsp        # This should have been $16 (or similar multiple of 16)

但是,我无法理解为什么在您的情况下会出现此错误。

© www.soinside.com 2019 - 2024. All rights reserved.