内存泄漏来自拆分和复制字符串

时间:2014-05-29 14:25:07

标签: c memory-leaks glibc

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

我对C很陌生,所以不要惊讶于我做错了什么,我似乎无法弄清楚是什么。我一直在尝试使用Valgrind缩小范围,但老实说输出有点超过我的头脑(运行应用程序生成的10k +行日志文件不到一分钟)。但是在挖掘该日志时,我确实发现一些函数反复显示永久丢失的块,所有这些都使用了类似的结构。

示例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);
}

非常感谢任何帮助!!

1 个答案:

答案 0 :(得分:1)

看起来你是免费的' ret'一旦调用g_free(holder2),但你已经为那一个免费做了多次分配 - 你多次调用parse_incoming_value,每次都会导致分配,但你只能在最后一次释放。

当你每次将holder2指针复制到schedule_info元素时,它们实际上有"泄露"最后的记忆。

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

e.g。

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);