0

我尝试编写我的第一个 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)
4

1 回答 1

2

你没有做错什么。GTK 小部件使用引用计数,但在您的程序中所有引用都得到处理,因此您不会(手动)泄漏任何东西。

那么为什么 Valgrind 声称你是?

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

其次,您可以设置G_DEBUG=gc-friendly,这应该有助于 Valgrind 产生更准确的结果(尽管根据我的经验,它通常没有任何区别)。

这两个环境变量都列在GLib 文档中。

不幸的是,即使你做了这两件事,Valgrind 仍然会报告你的应用程序泄漏内存。这样做的原因是 GTK(及其底层库)在启动时分配了一些“静态”内存,直到程序退出才被释放。这不是一个真正的问题,因为通常程序一gtk_main()返回就结束,然后操作系统释放任何剩余的资源,所以你并没有真正泄漏任何东西。Valgrind 认为你是,因此拥有一个gtk_deinit()函数会很好,但遗憾的是没有一个函数。

你能做的最好的事情就是通过抑制文件教 Valgrind 忽略这些事情。Gnome Wiki 上的Valgrind 页面包含所有这些以及更多内容的详细信息。

于 2013-10-16T08:02:15.730 回答