我正在学习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 内存,但是,内存泄漏警告仍然弹出。有人能帮我找出是哪些部分导致了问题吗?非常感谢。
不清楚为什么有人会建议“远离”特定的图书馆。只需 RTFM 并尝试了解您正在处理的问题。毕竟,这些库本身可能包含内存泄漏...... 您应该看看 Electric Fence,它用更易于调试的方式取代了 malloc 调用:https://elinux.org/Electric_Fence
记住字符串始终以 NUL 结尾,您的代码可以得到简化。完全避免内存复制,您不需要使用
strdup()
并单独处理输入缓冲区。
key
指针始终是缓冲区的开头,因此只需获取指向它的点并将第一个 @
字符替换为 0x00
。val
指针在搜索模式之后开始,因此您也可以在最后一个 @
字符之后获取指向内存位置的指针。buffer[MAX_LENGTH] = 0;
为了熟悉在 C 中完成此操作的方式,我建议您在非常基础的级别上实现模式匹配。创建一个 while 循环,扫描缓冲区中的每个字符并搜索分隔模式。当它连续敲击 4 次时,你就找到了你的指针。