c - 分割和复制字符串导致内存泄漏

标签 c memory-leaks glibc

我正在开发一个用 GTK+ 用 C 语言编写的相当简单的应用程序,该应用程序内存泄漏严重。它在定时器上有一些基本功能,用于检查时钟并轮询外部网络设备,解析返回的字符串。该应用程序在一个小型触摸板上运行,通过 TOP 我可以看到可用内存在运行时被耗尽。

我对 C 还很陌生,所以我做错了什么并不奇怪,我只是似乎不知道是什么。我一直在尝试使用 Valgrind 来缩小范围,但老实说,输出有点超出了我的想象(运行应用程序不到一分钟生成了 10k+ 行日志文件)。但在挖掘该日志时,我确实发现一些函数反复出现永久丢失的 block ,所有函数都使用一些类似的结构。

示例 1: 这是一个简短的函数,当选择一个选项时会调用它。 g_strdup_printf 的最后一行是 Valgrind 调用的。 select_next_show 和 select_show_ Five_displayed 都是全局变量。

static void show_box_five_clicked ()
{
g_timer_start(lock_timer);
gtk_image_set_from_file (GTK_IMAGE(select_show_1_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_2_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_3_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_4_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_5_cb_image), "./images/checkbox_checked.png");

select_next_show = g_strdup_printf("%i",select_show_five_displayed);

}  

示例 2: 这是另一个经常被调用的函数,并且在 Valgrind 日志中经常出现。它获取来自网络设备的传入响应,将其解析为两个字符串,然后返回一个。

static gchar* parse_incoming_value(gchar* incoming_message)
{
gchar *ret;

GString *incoming = g_string_new(incoming_message);
gchar **messagePieces = g_strsplit((char *)incoming->str, "=", 2);
ret = g_strdup(messagePieces[1]);
g_strfreev(messagePieces);

g_string_free(incoming, TRUE);
return ret;
}

在所有像这些导致问题的情况下,我都会释放一切可能的东西,而不会导致段错误,但我一定是错过了其他东西或做错了什么。

更新: 为了回答评论中的问题,以下是我如何使用解析函数以及释放返回值的示例(精简):

static void load_schedule ()
{
    ...other code...

    gchar *holder;
    gchar *holder2;

    holder = read_a_line(schedListenSocket);
    holder2 = parse_incoming_value(holder);
    schedule_info->regShowNumber = holder2;

    holder = read_a_line(schedListenSocket);
    holder2 = parse_incoming_value(holder);
    schedule_info->holidayShowNumber = holder2;

    ...other code....

    g_free(holder);
    g_free(holder2);
}

非常感谢任何帮助!!

最佳答案

看起来你在调用 g_free(holder2) 时释放了一次“ret”,但你已经为该释放做了多次分配 - 你多次调用 parse_incoming_value ,每次都会导致分配,但你只在以下位置释放一次结束。

当您每次将holder2指针复制到schedule_info元素中时,它们实际上在末尾具有“泄漏”内存。

如果你不在任何地方释放holder2,而是在代码末尾释放schedule_info中的所有元素。我认为这表明没有泄漏?

例如

holder2 = <result of dynamic alloc>;
schedule_info->a = holder2;
...
holder2 = <result of dynamic alloc>;
schedule_info->b = holder2;
...

// instead of g_free(holder2) at the end, do this...
g_free(schedule_info->a);
g_free(schedule_info->a);

关于c - 分割和复制字符串导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23935722/

相关文章:

c - 这种条件变量的使用是否总是受到丢失信号竞争的影响?

c - 函数调用和汇编

c - 实现内存调试器

c - gcc 和 glibc 版本

linux - GNU C 库 (glibc) 构建错误(找不到 libc-modules.h)

c - 在 C 中订购结构数组时出现问题

c - 如何使用<从文本文件中读取一整行

Java 双端队列/准备语句内存泄漏

java - 如何根据Sonar清理Java ThreadLocals?

linux - 如何链接到特定的 glibc 版本?