2013-07-18 1 views
4

Я пытаюсь понять, как правильно освободить память, когда я закончил виджет GTK, например, если мне нужно создать и уничтожить многие виджеты. Тем не менее, valgrind, похоже, указывает на утечку памяти, независимо от того, что я пытаюсь сделать. Я рассмотрел другие вопросы, в том числе тот, который содержит файл supression valgrind для GTK, но он не изменил результат.Как правильно (и эффективно) освобождать память в виджете gtk

Вот самый простой фрагмент кода, чтобы воспроизвести мой вопрос:

#include "gtk/gtk.h" 

int main() 
{ 
    GtkWidget * widget = gtk_fixed_new(); 
    g_object_ref(widget); 
    g_object_ref_sink(widget); // remove floating reference, and own this object ourselves 

    g_object_unref(widget); 

    gtk_widget_destroy(widget); 
} 

Я ожидаю, что (после того, как дело с плавающей ссылки), функция убрать ссылки() должна уменьшить счетчик ссылок до нуля, а затем вся память выпущен. Я выбрал gtk_widget_destroy() там для хорошей меры, но я не уверен, что это действительно необходимо (и это не меняет величину утечки).

Выход с командой VALGRIND G_SLICE=debug-blocks valgrind ./t3 --supression=~/Downloads/GNOME.supp от вопроса Memory Leaks in GTK hello_world program является

==10079== HEAP SUMMARY: 
==10079==  in use at exit: 164,338 bytes in 847 blocks 
==10079== total heap usage: 1,380 allocs, 533 frees, 219,176 bytes allocated 
==10079== 
==10079== LEAK SUMMARY: 
==10079== definitely lost: 0 bytes in 0 blocks 
==10079== indirectly lost: 0 bytes in 0 blocks 
==10079==  possibly lost: 21,350 bytes in 174 blocks 
==10079== still reachable: 142,988 bytes in 673 blocks 
==10079==   suppressed: 0 bytes in 0 blocks 
==10079== Rerun with --leak-check=full to see details of leaked memory 

Другая документация Я смотрел на это http://www.demko.ca/blog/posts/200705_gtkmm_refcoutning.txt и https://developer.gnome.org/gtk2/2.24/GtkObject.html

Вы можете скомпилировать мой сниппет с

gcc -std=gnu99 `pkg-config --cflags gtk+-2.0` t3.c -o t3 `pkg-config --libs gtk+-2.0 gthread-2.0` 

Кто-нибудь знает, что мне не хватает? Есть ли еще одна функция, которую я должен вызывать для обеспечения освобождения памяти?

ответ

3
- g_object_ref 

    Increases ref count by one 

- g_object_unref 

    Decreases ref count by one, if ref count == 0, the object is destroyed 

- g_object_ref_sink 

    IF the object has a floating ref, it converts that reference to a normal ref (sinks it) 
    ELSE it increases the ref count by one 

- All objects start with a floating ref count of 1 

Для некоторого дальнейшего чтения, я хотел бы предложить вам взглянуть на следующие статьи: Introduction to Memory Management in GTK+

Теперь, двигаясь по вашему примеру, позволяет взглянуть на вызовы функций и что они делают:

GtkWidget * widget = gtk_fixed_new(); //widget created with ref count of 1 | floating = true 
g_object_ref(widget); // floating = true, ref count increased to 2 
g_object_ref_sink(widget); // floating = false, ref count remains at 2 

g_object_unref(widget); // floating = false, ref count decreases to 1 

//No further unrefs, hello leak! 

Я надеюсь, что это объяснит вашу утечку, обязательно прочитайте статью, упомянутую выше.

+0

Но не 'gtk_widget_destroy()' unref it еще раз? Происходит ли утечка, если вы удаляете вызов 'g_object_ref()'? Я скорее думаю, что ответ может быть вызван тем, что GLib не очень хорошо сотрудничает с Valgrind. – ptomato

+1

'gdk_destroy()' просто посылает сигнал, чтобы вежливо попросить всех удалить их ссылки, но не заставляет ссылаться на какие-либо ссылки. Проблема заключалась в том, что я как-то неправильно понял эффект 'ref_sink()', который НЕ нужно связывать с вызовом 'ref()'. – jstrom

+0

Вау, это совершенно противоположное поведение [g_closure_sink] (https://developer.gnome.org/gobject/stable/gobject-Closures.html#g-closure-sink). – Friedrich