You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50拼写器作业:malloc初始正常,循环多次后报corrupted top size错误

CS50 Speller作业:malloc(): corrupted top size错误分析

我正在完成CS50的拼写器作业,仅修改了dictionary.c文件,使用djb2哈希算法实现。运行时出现错误:

malloc(): corrupted top size
Aborted (core dumped)

调试发现加载前10个词(直至aardwolf)正常,存入aardwolf后调用malloc触发错误。以下是我的代码:

// Implements a dictionary's functionality

#include <ctype.h>
#include <stdbool.h>
#include <stdio.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;

// Choose number of buckets in hash table
const unsigned int N = 100;

// Variable to count number of words loaded into dictionary
int count = 0;

// 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)
{
    // Improve this hash function
    unsigned long hash = 5381;
    int c;
    while((c = *word++))
    {
        hash = (((hash << 5) + hash) + c);
    }
    int hash_value = hash % N;
    return hash_value;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // TODO
    FILE *dict_file = fopen(dictionary, "r");
    if (dict_file == NULL)
    {
        printf("Could not open %s.\n", dictionary);
        return false;
    }
    for(int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }
    char c;
    int i = 0;
    node *new_node = malloc(sizeof(node));
    while (fread(&c, sizeof(char), 1, dict_file))
    {
        // printf("%c", c);
        if(c != '\n')
        {
            new_node -> word[i] = c;
            i++;
        }
        else
        {
            int key = hash(new_node -> word);
            new_node -> next = table[key];
            table[key] = new_node;
            // printf("%lu", sizeof(node));
            new_node = malloc(sizeof(node));
            count++;
        }
    }
    fclose(dict_file);
    if(count > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
    // TODO
    if(count > 0)
    {
        return count;
    }
    else
    {
        return 0;
    }
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // TODO
    for(int i = 0; i < N; i++)
    {
        node *temp_node = NULL;
        while(table[i] != NULL)
        {
            temp_node = table[i] -> next;
            free(table[i]);
            table[i] = temp_node;
        }
    }
    return false;
}

错误原因分析

  1. 字符串未添加终止符:
    读取单词时,遇到换行符直接存入哈希表,但new_node->word数组没有添加'\0'。hash函数会一直读取内存直到遇到0字节,这会越界访问node结构体之外的堆内存,破坏堆的元数据。

  2. 未重置单词索引i:
    每个单词处理完后,i没有重置为0,下一个单词会从word数组的当前位置继续写入,直接覆盖node结构体中的next指针区域,彻底破坏堆结构,导致后续malloc检测到堆损坏并抛出错误。

  3. 最后一个单词未处理:
    如果字典文件最后一行没有换行符,最后一个单词永远不会被加入哈希表,还会残留一个未使用的malloc节点,可能引发额外内存问题。

  4. unload函数返回错误值:
    虽然不是直接导致当前错误,但unload函数完成内存释放后返回false,属于逻辑错误。

修正后的关键代码片段

修改load函数中的换行处理逻辑,添加字符串终止符并重置索引:

else
{
    new_node->word[i] = '\0'; // 添加字符串终止符
    int key = hash(new_node->word);
    new_node->next = table[key];
    table[key] = new_node;
    count++;
    i = 0; // 重置索引,准备下一个单词
    new_node = malloc(sizeof(node));
    // 检查内存分配是否成功
    if (new_node == NULL)
    {
        fclose(dict_file);
        unload();
        return false;
    }
}

循环结束后处理最后一个无换行符的单词:

// 处理文件末尾没有换行符的最后一个单词
if (i > 0)
{
    new_node->word[i] = '\0';
    int key = hash(new_node->word);
    new_node->next = table[key];
    table[key] = new_node;
    count++;
}
else
{
    // 释放未使用的节点
    free(new_node);
}

同时修正unload函数的返回值:

bool unload(void)
{
    for(int i = 0; i < N; i++)
    {
        node *temp_node = NULL;
        while(table[i] != NULL)
        {
            temp_node = table[i]->next;
            free(table[i]);
            table[i] = temp_node;
        }
    }
    return true; // 释放成功返回true
}

内容的提问来源于stack exchange,提问作者esp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 06:00:25