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 には、 と呼ばれる独自の「スラブ」メモリ アロケータがありますGSlice。これは、一般にシステムよりもmalloc小さな割り当てのほうが高速です。残念ながら、これは Valgrind を混乱させますが、環境変数を設定するとG_SLICE=always-mallocGSlice効果的にオフになります。

第二に、Valgrind がより正確な結果を生成するのに役立つはずの を設定できG_DEBUG=gc-friendlyます (私の経験では一般的に違いはありません)。

これらの環境変数は両方とも、GLib のドキュメントにリストされています。

残念ながら、これらの両方を行ったとしても、Valgrind はアプリがメモリ リークを報告します。この理由は、GTK (およびその基礎となるライブラリ) が起動時に「静的」メモリを割り当て、プログラムが終了するまで解放されないためです。通常、プログラムはgtk_main()戻るとすぐに終了し、OS は残りのリソースを解放するため、実際には何もリークしていないため、これは実際には問題ではありません。Valgrind はあなたがそうであると考えています。このため、関数があればいいのですがgtk_deinit()、残念ながら関数はありません。

代わりにできる最善の方法は、抑制ファイルを介して、これらのことを無視するように Valgrind に教えることです。Gnome WikiのValgrind ページには、これらすべての詳細が記載されています。

于 2013-10-16T08:02:15.730 に答える