Valgrind 仍然显示可以使用 addrec() 访问内存

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

以下代码用于创建和管理哈希表: 哈希.c:

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


typedef struct node {
    record_t rec;
    struct node *next;
} node_t;

node_t *hashArray [MAX_SIZE];

void initHashTable() {
    for(int i = 0; i < MAX_SIZE; i++) {
        hashArray[i] = NULL;
    }
}


int myHashFunc(long long phone_num)
{
    return phone_num % MAX_SIZE;
}

int searchRecord(long long phone, record_t *record)
{
    int hix;
    node_t *ptmp;

    hix = myHashFunc(phone);
    ptmp = hashArray[hix];
    if(ptmp->rec.phone == phone){
        *record = (ptmp->rec);
        return SUCCESS;
    }

    while(ptmp){
        if(ptmp->rec.phone == phone){
            *record = ptmp->rec;
            return SUCCESS;
        }
        ptmp = ptmp->next;
    }
    return NOT_FOUND_ERR;
}

int addRec(record_t *rec)
{
    int hix;
    node_t *pn = (node_t *)malloc(sizeof(node_t));
    if(pn == NULL) return NO_MEMORY_ERR;

    pn->rec = *rec;

    hix = myHashFunc(rec->phone);
    pn->next = hashArray[hix];
    hashArray[hix] = pn;

    return SUCCESS;
}

int delRec(long long phone)
{
    int hix;
    node_t *ptmp, *delnode;

    hix = myHashFunc(phone);
    ptmp = hashArray[hix];

    if(ptmp == NULL || ptmp == 0){
        return NOT_FOUND_ERR;
    }

    if(ptmp->rec.phone == phone){
        delnode = ptmp;
        hashArray[hix] = ptmp->next;
        free(delnode);
        return SUCCESS;
    }

    while(ptmp->next){
        if(ptmp->next->rec.phone == phone){
            delnode = ptmp->next;
            ptmp->next = ptmp->next->next;
            free(delnode);
            return SUCCESS;
        }
        ptmp = ptmp->next;
    }
    return NOT_FOUND_ERR;
}

void displayAllRecords()
{
    int i;
    node_t *ptmp;
    printf("Name                    Phone Number\n");
    printf("--------------------    ----------\n");
    for(i = 0; i < MAX_SIZE; i++){
        ptmp = hashArray[i];
        while(ptmp){
            printf("%19s    %10lld\n",ptmp->rec.name, ptmp->rec.phone);
            ptmp = ptmp->next;
        }
    }
}

int destroyhash()
{
    int i;
    node_t *temp, *curr;
    for(i = 0; i < MAX_SIZE; i++){
        curr = hashArray[i];
        while(curr != NULL){
            temp = curr;
            curr = curr->next;
            free(temp);
        }
    }
}


test.c: #include <stdio.h>
#include "hash.h"
enum{SER = 1, ADD, DEL, DISP, XIT};

int main()
{
    struct record rec;
    int option, state;
    void initHashTable();
    while(1)
    {
        printf("Enter 1:To search and get, 2: Add a record, 3: Delete a record\n");
        printf("Enter your option: ");
        scanf("%d", &option);
        long long phone;
        switch(option)
        {
            case SER:
                printf("Enter the phone number to search\n");
                scanf("%lld",&phone);
                state = searchRecord(phone, &rec);
                if(state == SUCCESS)
                    printf("Name: %s, phone: %lld\n", rec.name, rec.phone);
                else
                    printf("Search failed with error %d\n", state);
                break;
            case ADD:
                printf("Enter phone number: \n");
                scanf("%lld",&rec.phone);
                getc(stdin);
                printf("Enter name\n");
                scanf("%[^\n]",rec.name);
                state = addRec(&rec);
                if(state == SUCCESS)
                    printf("Record added successfully\n");
                else
                    printf("Record addition failed with error %d\n", state);
                break;
            case DEL:
                printf("Enter phone number to search\n");
                scanf("%lld",&phone);
                state = delRec(phone);
                if(state == SUCCESS)
                    printf("Record deleted successfully\n");
                else
                    printf("Record deletion failed with error %d\n", state);
                break;
            case DISP:
                displayAllRecords();
                break;
            case XIT:
                return 0;
                break;
        }
    }
    int destroyhash();
}


这是 valgrind 的输出:

==68577== Memcheck, a memory error detector
==68577== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==68577== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==68577== Command: ./myprog arg1 arg2
==68577== Parent PID: 37429
==68577== 
==68577== 
==68577== HEAP SUMMARY:
==68577==     in use at exit: 160 bytes in 4 blocks
==68577==   total heap usage: 7 allocs, 3 frees, 2,248 bytes allocated
==68577== 
==68577== 160 bytes in 4 blocks are still reachable in loss record 1 of 1
==68577==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==68577==    by 0x1095C6: addRec (in /home/biggmacbilly/adv_C/hash/myprog)
==68577==    by 0x10938E: main (in /home/biggmacbilly/adv_C/hash/myprog)
==68577== 
==68577== LEAK SUMMARY:
==68577==    definitely lost: 0 bytes in 0 blocks
==68577==    indirectly lost: 0 bytes in 0 blocks
==68577==      possibly lost: 0 bytes in 0 blocks
==68577==    still reachable: 160 bytes in 4 blocks
==68577==         suppressed: 0 bytes in 0 blocks
==68577== 
==68577== For lists of detected and suppressed errors, rerun with: -s
==68577== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

valgrind 输出显示我在 addrec 和 main 函数中存在内存泄漏。这是我第一次使用 valgrind,我无法找出给定程序中的内存泄漏。我该如何修复这些内存泄漏?预先感谢您。

valgrind 命令: valgrind --leak-check=full --show-leak-kinds=all --log-file="output.txt" ./myprog 使用的编译器:GCC

c memory-leaks valgrind
1个回答
0
投票

像往常一样,在 C 语言中重新发明方轮是一个问题。

使用 C++ 和

std::unordered_map
。您将需要四分之一的代码,而 C++ 的 RAII 将使您的代码更难泄漏。类似的论点也适用于 Rust,尽管这是一个更大的进步。

正如评论中所说,你没有打电话给

destroyhash()

此外,除了为 XIT 点击“5”之外,我没有看到任何摆脱“while (1)”循环的方法。从 main 返回。据我所知,你放置“destroyhash()”的地方是无法访问的。

以下应该完成这项工作:

            case XIT:
                destroyhash();
                return 0;
© www.soinside.com 2019 - 2024. All rights reserved.