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

哈希表内存释放报错原因排查及解决方法咨询

哈希表初始化与内存释放崩溃问题分析

问题背景

我正在自学C语言(非院校学习),学习过程中尝试实现哈希表数据结构,但遇到了内存释放崩溃的问题。以下是可复现代码:

#include <stdio.h>
#include <stdlib.h>

struct table_item {
    char *name;
    char gender;
    char *birthdate;
    char *address;
};

struct list_node {
    struct table_item *data;
    struct list_node *next;
    unsigned long long hash_key;
};

struct hashtable {
    int table_size;
    int num_entries;
    struct list_node **entries;
};

struct hashtable* init_hashtable(int size);
void free_hashtable(struct hashtable *table);

int main(void)
{
    struct hashtable *hashtable = NULL;
    int size_entry = 0;
    
    printf("Input hashtable array size: ");
    while (size_entry < 1) {
        scanf(" %d", &size_entry);
    }
    hashtable = init_hashtable(size_entry);

    free_hashtable(hashtable);

    return 0;
}

struct hashtable* init_hashtable(int size) {
    struct hashtable* new_table;
    if ((new_table = malloc(sizeof(struct hashtable))) == NULL) {
        perror("Error: failed to allocate memory for hash table\n");
        exit(EXIT_FAILURE);
    }
    new_table->table_size = size;
    new_table->num_entries = 0;
    if ((new_table->entries = malloc(size*sizeof(struct list_node))) == NULL) {
        perror("Error: failed to allocate memory for hash table array\n");
        exit(EXIT_FAILURE);
    }

    return new_table;
}

void free_hashtable(struct hashtable *table) {

    for (int i = 0; i < table->table_size; i++) {
        if (table->entries[i] != NULL) {
            free_list(table->entries[i]);
            table->entries[i] = NULL;
        }
    }

    free(table->entries);
    free(table);
}

运行程序时,即使未向哈希表添加任何数据,调用free_hashtable释放内存时总会崩溃。通过GDB调试发现,free_hashtable的for循环中if (table->entries[i] != NULL)条件总会触发(比如i=0时),导致free_list函数尝试释放非法内存,进而产生栈转储。看起来table->entries[i]并非NULL,而是无效的struct list_node*值,导致条件被错误触发。

我原本希望通过该循环遍历entries数组,仅释放已malloc分配的节点内存,但目前程序会直接崩溃,不知道该如何修改才能达到预期效果。


问题原因分析

  • malloc内存未初始化:init_hashtable中用malloc分配的entries数组,不会自动将内存初始化为NULL,数组元素都是随机垃圾值。这些垃圾值大概率非NULL,导致if条件误判,触发非法内存释放操作。
  • 内存分配类型不匹配:struct hashtable的entries是struct list_node**(指针数组),但分配内存时用了size*sizeof(struct list_node),正确应该是size*sizeof(struct list_node*),内存分配大小错误会加剧非法访问问题。

修复方案

  1. 修正内存分配大小
    在init_hashtable中,将entries的分配代码改为:

    if ((new_table->entries = malloc(size * sizeof(struct list_node*))) == NULL) {
        perror("Error: failed to allocate memory for hash table array\n");
        exit(EXIT_FAILURE);
    }
    

    因为entries是指针数组,每个元素是struct list_node*类型,需分配对应指针大小的空间。

  2. 初始化数组元素为NULL
    分配完entries后,将所有元素初始化为NULL,确保后续判断逻辑准确:

    • 方法一(需包含<string.h>头文件):
      memset(new_table->entries, 0, size * sizeof(struct list_node*));
      
    • 方法二:
      for (int i = 0; i < size; i++) {
          new_table->entries[i] = NULL;
      }
      
  3. 补充free_list函数实现
    原代码仅声明了free_list未实现,需补充完整以正确释放链表节点及内部数据:

    void free_list(struct list_node *node) {
        struct list_node *temp;
        while (node != NULL) {
            temp = node;
            node = node->next;
            // 释放table_item内的动态分配内存
            free(temp->data->name);
            free(temp->data->birthdate);
            free(temp->data->address);
            free(temp->data); // 释放table_item结构体
            free(temp); // 释放链表节点
        }
    }
    

    同时在代码开头添加函数声明:void free_list(struct list_node *node);。

内容的提问来源于stack exchange,提问作者A-PSquestions

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:45:47