C 程序中的内存泄漏

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

我正在学习C编程。作为一个新手,我不得不说这门语言真的很难,尤其是内存管理。我以前用Java和Python编程,不用担心内存泄漏。然而,这与 C 完全是另一回事。最近我写了一个小程序,我用 valgrind 运行它,它说该程序导致内存泄漏。代码已粘贴。

#include <stdio.h>
#include <glib.h>
#include <string.h>
#define MAX_LENGTH 256
#define TOKEN_NUM 2

char *tokArr[MAX_LENGTH];

char** strSplit(char *oneStr, const char* delim)
{
    char *localStr = oneStr;
    int index = 0;
    char *token = strtok(localStr, delim);

    while (token != NULL) {
        tokArr[index++] = token;
        token = strtok(NULL, delim);
    }
    free(token);
    return tokArr;
}

void printHash(gpointer key, gpointer val, gpointer userData)
{
    printf(userData, key, val);
    free(key);
    free(val);
}

int main(int argc, char const *argv[])
{   
    if (argc != 2) {
        printf("need a file name as an argument");
        return -1;
    }

    const char *filePath = argv[1];
    FILE *fp = fopen(filePath, "r");

    if (fp == NULL) {
        printf("error: cannot open document %s", filePath);
        return -1;
    }

    GHashTable* hash = g_hash_table_new(g_str_hash, g_str_equal);
    char buffer[MAX_LENGTH];
    while (fgets(buffer, MAX_LENGTH, fp)) {
        char **splitedStr = strSplit(buffer, "@@@@");
        char *key = strdup(splitedStr[0]);
        char *val = strdup(splitedStr[1]);
        g_hash_table_insert(hash, key, val);
        free(splitedStr);
    }
    fclose(fp);
    g_hash_table_foreach(hash, (GHFunc)printHash, "Name: %s, age: %s\n");
    g_hash_table_destroy(hash);
    return 0;
}

如您所见,这个程序非常简单。它逐行读取文本文件。然后每一行将被分成两部分,并用字符串“@@@@”分隔。接下来,该行的第一部分作为键存储到哈希表中,该行的第二部分作为值。本程序使用了GLib-2.0提供的哈希表。

我尽力释放所有可能的 malloc 内存,但是,内存泄漏警告仍然弹出。有人能帮我找出是哪些部分导致了问题吗?非常感谢。

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

不清楚为什么有人会建议“远离”特定的图书馆。只需 RTFM 并尝试了解您正在处理的问题。毕竟,这些库本身可能包含内存泄漏...... 您应该看看 Electric Fence,它用更易于调试的方式取代了 malloc 调用:https://elinux.org/Electric_Fence

记住字符串始终以 NUL 结尾,您的代码可以得到简化。完全避免内存复制,您不需要使用

strdup()
并单独处理输入缓冲区。

  • 您的
    key
    指针始终是缓冲区的开头,因此只需获取指向它的点并将第一个
    @
    字符替换为
    0x00
  • 您的
    val
    指针在搜索模式之后开始,因此您也可以在最后一个
    @
    字符之后获取指向内存位置的指针。
  • 棘手的部分是确保您使用 fgets 读取的内容确实在末尾有一个 NUL 终止字符:
    buffer[MAX_LENGTH] = 0;

为了熟悉在 C 中完成此操作的方式,我建议您在非常基础的级别上实现模式匹配。创建一个 while 循环,扫描缓冲区中的每个字符并搜索分隔模式。当它连续敲击 4 次时,你就找到了你的指针。

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