为什么以下程序会泄漏内存?

时间:2013-10-15 19:16:32

标签: memory-leaks gtk

我试着写第一个GTK +程序。汇编很顺利,但valgrind说存在内存泄漏。我找不到那些人,所以有人可以说我做错了什么?或者是否可以编写没有内存泄漏的图形化Linux程序?

#include <gtk/gtk.h>

int main(int argc, char* argv[])
{
        gtk_init(&argc, &argv);

        GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window), "Hello World");

        gtk_container_set_border_width(GTK_CONTAINER(window), 60);

        GtkWidget* label = gtk_label_new("Hello, world!");
        gtk_container_add(GTK_CONTAINER(window), label);

        g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

        gtk_widget_show_all(window);

        gtk_main();

        return 0;
}

gcc -Wall gtkhello.c -o gtkhello $(pkg-config --cflags --libs gtk+-2.0)

valgrind -v ./gtkhello

...
==9395== HEAP SUMMARY:
==9395==     in use at exit: 538,930 bytes in 6,547 blocks
==9395==   total heap usage: 21,434 allocs, 14,887 frees, 2,964,543 bytes allocated
==9395== 
==9395== Searching for pointers to 6,547 not-freed blocks
==9395== Checked 949,656 bytes
==9395== 
==9395== LEAK SUMMARY:
==9395==    definitely lost: 4,480 bytes in 30 blocks
==9395==    indirectly lost: 5,160 bytes in 256 blocks
==9395==      possibly lost: 180,879 bytes in 1,716 blocks
==9395==    still reachable: 348,411 bytes in 4,545 blocks
==9395==         suppressed: 0 bytes in 0 blocks
==9395== Rerun with --leak-check=full to see details of leaked memory
==9395== 
==9395== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==9395== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

1 个答案:

答案 0 :(得分:1)

你没有做错任何事。 GTK小部件使用引用计数,但在您的程序中所有引用都被处理,因此您不会(手动)泄漏任何内容。

那么为什么Valgrind声称你是谁?

首先,GLib有自己的“slab”内存分配器,称为GSlice,对于小分配,它通常比系统malloc更快。不幸的是,它让Valgrind感到困惑,但是如果你设置环境变量G_SLICE=always-mallocGSlice就会被有效关闭。

其次,你可以设置G_DEBUG=gc-friendly,这可以帮助Valgrind产生更准确的结果(虽然我的经验一般没有任何区别)。

这两个环境变量都列在GLib documentation

不幸的是,即使您同时执行这两项操作,Valgrind仍会报告您的应用程序泄漏了内存。原因是GTK(及其底层库)在启动时分配了一些“静态”内存,在程序退出之前不会被释放。这不是一个真正的问题,因为通常程序会在gtk_main()返回后立即结束,然后操作系统会释放所有剩余资源,因此您不会真正泄漏任何内容。 Valgrind认为你是,但由于这个原因,拥有gtk_deinit()函数会很好,但遗憾的是没有。{/ p>

你能做的最好的事情就是通过一个抑制文件来教导Valgrind忽略这些事情。 Valgrind page on the Gnome Wiki详细介绍了所有这些以及更多内容。