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

C语言:如何保留结构体内存防止被覆盖?哈希表链表节点改写求助

分离链接哈希表内存覆盖问题的修复方案

核心问题分析

你的代码出现内存覆盖、节点数据乱码的根本原因是所有链表节点、链表结构都在栈上分配局部变量,函数执行完毕后栈帧被销毁,这些内存会被后续函数(比如hash、tableGet)的栈数据覆盖。除此之外还有几个细节错误:

  • 字符串比较用==,这是比较指针地址而非内容,应该用strcmp
  • 哈希函数里的sum未初始化,会导致哈希值随机,定位错误的哈希桶
  • 哈希表和链表操作采用传值调用,会产生不必要的拷贝,也容易引发内存问题

修复步骤

  1. 改用堆内存分配:用malloc为Node、List分配堆内存,确保函数返回后内存不会被回收
  2. 修复字符串比较逻辑:用strcmp替代==比较姓名
  3. 初始化哈希函数的sum变量:避免随机哈希值
  4. 修改函数为指针传递:哈希表的添加、查询操作都传递指针,避免拷贝,保证操作作用于原表
  5. 修正链表操作的指针逻辑:确保链表节点的指针指向堆内存的有效地址

完整修复代码

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

typedef struct Node {
    int val;
    int savedAge;
    char savedName[100];
    struct Node* next;
} Node;

typedef struct {
    int age;
    char name[100];
} Person;

typedef struct {
    Node* head;
    Node* tail;
} List;

typedef struct {
    List* table[100];
} HashTable;

int hash(Person*);

Person person(int age, char name[]) {
    Person p;
    p.age = age;
    strcpy(p.name, name);
    return p;
}

// 动态创建节点
Node* createNode(int val, Person p, Node* next) {
    Node* n = (Node*)malloc(sizeof(Node));
    if (!n) {
        perror("malloc failed for Node");
        exit(EXIT_FAILURE);
    }
    n->val = val;
    strcpy(n->savedName, p.name);
    n->savedAge = p.age;
    n->next = next;
    return n;
}

// 动态创建带头节点的链表
List* createList() {
    List* l = (List*)malloc(sizeof(List));
    if (!l) {
        perror("malloc failed for List");
        exit(EXIT_FAILURE);
    }
    // 创建哨兵节点
    l->head = createNode(-1, person(0, "SENTINEL"), NULL);
    l->tail = l->head;
    return l;
}

// 向链表添加节点
void listAdd(List* l, int val, Person p) {
    Node* newNode = createNode(val, p, NULL);
    l->tail->next = newNode;
    l->tail = newNode;
}

// 初始化哈希表
HashTable* createHashTable() {
    HashTable* t = (HashTable*)malloc(sizeof(HashTable));
    if (!t) {
        perror("malloc failed for HashTable");
        exit(EXIT_FAILURE);
    }
    // 初始化所有桶为NULL
    for (int i = 0; i < 100; i++) {
        t->table[i] = NULL;
    }
    return t;
}

// 向哈希表添加键值对
void tableAdd(HashTable* t, Person key, int val) {
    int num = hash(&key) % 100;
    // 处理负数哈希值(如果有的话)
    if (num < 0) num += 100;
    if (t->table[num] == NULL) {
        t->table[num] = createList();
    }
    listAdd(t->table[num], val, key);
}

// 从哈希表查询值
int tableGet(HashTable* t, Person key) {
    int position = hash(&key) % 100;
    if (position < 0) position += 100;
    List* listLoc = t->table[position];
    if (listLoc == NULL) {
        return -1;
    }
    Node* curr = listLoc->head->next; // 跳过哨兵节点
    while (curr != NULL) {
        if (curr->savedAge == key.age && strcmp(curr->savedName, key.name) == 0) {
            return curr->val;
        }
        curr = curr->next;
    }
    return -1;
}

// 修复后的哈希函数
int hash(Person* p) {
    int sum = 0; // 初始化sum
    int i = 0;
    char nameChar = p->name[i];
    while (nameChar != '\0'){
        sum += (int)nameChar;
        i += 1;
        nameChar = p->name[i];
    }
    return p->age + sum;
}

// 清理哈希表内存(可选,避免内存泄漏)
void freeHashTable(HashTable* t) {
    for (int i = 0; i < 100; i++) {
        if (t->table[i] != NULL) {
            Node* curr = t->table[i]->head;
            while (curr != NULL) {
                Node* temp = curr;
                curr = curr->next;
                free(temp);
            }
            free(t->table[i]);
        }
    }
    free(t);
}

int main() {
    Person bob = person(36, "Robert");
    printf("%s\n", bob.name);
    HashTable* tab = createHashTable();
    tableAdd(tab, bob, 3);
    printf("Added Robert to table as 3\n");
    int val = tableGet(tab, bob);
    if (val == 3) {
        printf("Success!\n");
    } else {
        printf("Failure, val is %d\n", val);
    }
    freeHashTable(tab); // 释放内存
    return 0;
}

关键修复说明

  • 新增createNode、createList、createHashTable函数,用malloc分配堆内存,确保内存长期有效
  • listAdd直接创建新节点并添加,不再依赖局部变量
  • tableGet直接遍历指针,避免拷贝节点导致的栈问题,同时用strcmp比较姓名
  • 哈希函数初始化sum为0,避免随机值
  • 添加内存清理函数freeHashTable,避免内存泄漏
  • 所有哈希表操作都传递指针,避免拷贝整个哈希表的开销和错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:35:27