为以结构作为值的动态分配的哈希图释放内存 - C

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

我已经遵循了一些关于 c 中的哈希图的教程。从代码中你可能可以看出我严重依赖于this实现,它有一个很好的后续视频,他在其中重新访问它以展示他如何释放哈希图link

我的问题是在创建和销毁哈希图时我似乎无法消除内存泄漏。我已经插入了 Visual Studio 提供的内存泄漏功能,但我似乎无法让它告诉我泄漏发生在哪一行:

Detected memory leaks!
Dumping objects ->
{89} normal block at 0x0000026818DA0E80, 8 bytes long.
 Data: <    h   > E0 0D DA 18 68 02 00 00 
Object dump complete.

我知道我可能为某个变量分配了错误大小的东西,但我花了几天时间查看代码,但似乎找不到它。

在 hashmap.c 中使用插入函数 - HashMapInsert() 时,我遇到了另一个内存泄漏:

Detected memory leaks!
Dumping objects ->
{95} normal block at 0x000001CBB57C0DE0, 8 bytes long.
 Data: <        > CD CD CD CD CD CD CD CD 
{89} normal block at 0x000001CBB57C10B0, 8 bytes long.
 Data: <  |     > 90 12 7C B5 CB 01 00 00 
Object dump complete.

我有一种感觉,这是我的结构条目->下一个指针,但我尝试在 hashmap.c 中的 freeEntry() 函数中释放它,并且泄漏仍然存在。任何帮助将不胜感激。

下面是一个最小的可重现示例(我认为)。我在 HashMapDelete 函数末尾附近尝试了 free(hmp->entries) 但出现错误(堆损坏错误)。我也在 freeEntry 函数中尝试了 free(e->next) 但没有成功。我认为问题与 HashMapCreate 中的 calloc 有关,但我不知道要更改什么来测试与实现的方式不同的方式。

哈希图.h

#pragma once
#ifndef HASHMAP_H
#define HASHMAP_H

#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>

typedef struct entry {
    char* key;
    double* value;
    struct entry* next;
} entry;

typedef struct hashmap {
    size_t* size;
    entry** entries;
} hashmap;

uint64_t HashMapHash(char* key, size_t size);
hashmap* HashMapCreate(size_t size);
bool HashMapInsert(hashmap* hmp, char* key, double value);
void HashMapPrint(hashmap* hmp);
void HashMapDelete(hashmap* hmp);

#endif`

hashmap.c

#include "hashmap.h"

hashmap* HashMapCreate(size_t size) {
    printf("\nHello Hash World!!!");

    hashmap* hmp = malloc(sizeof(hashmap*));

    if (hmp == NULL) {
        return NULL;
    }

    hmp->size = malloc(sizeof(size_t));

    if (hmp->size == NULL) {
        return NULL;
    }

    *hmp->size = size;

    hmp->entries = calloc(*hmp->size, sizeof(entry*));

    return hmp;
}

uint64_t HashMapHash(char* key, size_t size) {
    
    uint64_t hashVal = 1;

    for (int i = 0; i < strlen(key); i++) {
        hashVal += key[i];
        hashVal = (hashVal * key[i]) % size;
    }

    return hashVal;
}

bool HashMapInsert(hashmap* hmp, char* key, double value) {
    if (hmp == NULL || key == NULL) {
        return false;
    }

    entry* tmp = HashMapGet(hmp, key);

    if (tmp != NULL) {
        return false;
    }

    uint64_t idx = HashMapHash(key, *hmp->size);

    entry* e = malloc(sizeof(entry));

    if (e == NULL) {
        return false;
    }

    e->key = malloc(strlen(key)+1);

    if (e->key == NULL) {
        free(e);
        return false;
    }
    printf("\nSize of %s: %zu", key, strlen(key));
    strcpy_s(e->key, strlen(key) + 1, key);

    e->value = malloc(sizeof(double));

    if (e->value == NULL) {
        free(e->key);
        free(e);
        return false;
    }

    *e->value = value;

    e->next = malloc(sizeof(entry*));

    if (e->next == NULL) {
        free(e->key);
        free(e->value);
        free(e);
        return false;
    }

    e->next = hmp->entries[idx];
    hmp->entries[idx] = e;

    return true;
}

void freeEntry(entry* e) {
    free(e->value);
    free(e->key);
    //free(e->next);
    free(e);
}

void HashMapPrint(hashmap* hmp) {

    entry* node = NULL;

    printf("\nStart");
    for (int i = 0; i < *hmp->size; i++) {
        printf("\n[%-3d]: ", i);
        node = hmp->entries[i];
        while (node != NULL) {
            printf("%-10s | ", node->key);
            node = node->next;
        }
    }
    printf("\nEnd");
}

void HashMapDelete(hashmap* hmp) {
    if (hmp == NULL) {
        return;
    }

    entry* tmp = NULL;

    for (int i = 0; i < *hmp->size; i++) {

        while (hmp->entries[i] != NULL) {
            tmp = hmp->entries[i];
            hmp->entries[i] = hmp->entries[i]->next;
            freeEntry(tmp);
        }

        free(hmp->entries[i]);
    }

    HashMapPrint(hmp);

    free(hmp->entries);
    free(hmp->size);
}

main.c

#define _CRTDBG_MAP_ALLOC

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <inttypes.h>
#include <string.h>
#include <crtdbg.h>

#include "HashMapLib/hashmap.h"

int main() {

    size_t size = 10;
    
    hashmap* hmp = HashMapCreate(size);

    HashMapDelete(hmp);

    _CrtDumpMemoryLeaks();
}
c struct hashmap dynamic-memory-allocation free
1个回答
0
投票

泄漏是因为这两行:

e->next = malloc(sizeof(entry*));

// ...

e->next = hmp->entries[idx];

第一行分配内存,并将结果赋给

e->next
。然后下一行用另一个指针覆盖
e->next
。这会让你失去原来的指针。

简单的解决方案是删除第一行,并进行分配。

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