goran kirra net writes:
we can not free memory we have passed to libgtk+ so generic DESTROYs aren't working. There are "ref count" variables in some struct that can be usable We should be more careful about freeing memory but I think it requires an inteligent decision in every case individually.
I've been working on that topic since yesterday, with even some kind help from Sven Neumann[1], and I'd like to show my code proposal so far. One has to know that there are 3 classes of objects to distinguish: - the GtkObject hierarchy - the GObject hierarchy that don't inherit from GtkObject as well - structs (things such as GdkColor, GtkTextIter, etc) In the GtkObject hierarchy, objects that are not toplevel widgets are created in the "floating" state. It means that they don't have yet a parent. Then when they are associated with another object (box_pack and container_add), this floating state disappears. The nice thing is that when the "top" parent gets destroyed (the GtkWindow) it will free up the associated memory of its whole child tree. So basically for that hierarchy, we: - explicitely gtk_widget_destroy when a Gtk2::Window gets DESTROY'ed - could explicitely gtk_object_sink all widgets that are still in the "floating" state, but this would require tricky operations[2], so I suggest to ignore them (there won't be much harm to leak memory of objects the user creates without using them, because no one wants to do that in the long term) In the GObject hierarchy, objects use the normal refcounting strategy, (without the "floating" state). The problem is that some GObject are given back to the user already owned by another widget (for example Gtk2::TextView::get_buffer) while some not (for example Gtk2::Style::new), and Sven confirmed that there is no function/macro to query a GObject for that property. So we have two solutions here: 1. do it for the user - but then we need to split up the perl object creators by hand, to remember that some objects are only references to existing objects that won't need to be freed up, and some others not; 2. let the user do it - that means, when she creates a Gtk2::Style, she needs to $style->unref() it before it's destroyed, if she wants to not leak memory; The -2- is my preferred solution, since -1- needs that we do extra care to call the right perl object creator if we don't want to segfault (if we unref a buffer returned by get_buffer, the program will segfault when the textview gets destroyed). The bad side of -2- is that it's not consistent with what we do in the GtkObject hierarchy; e.g. there is implicit calling of gtk_widget_destroy in the DESTROY of Gtk2::Window, but explicit unref for GObject's. I have implemented the necessary code for -1-, though. As for structs, we explicitely g_malloc the associated memory (GdkColor etc), so the easy solution is that all the perl object wrappers for structs inherit from Gtk2::Struct in which we put a DESTROY that explicitely g_free the associated memory. Please find attached the code proposal (the GdkWindow also needs to be explicitely destroyed, this time with gdk_window_destroy):
Attachment:
jkiu
Description: Binary data
My tests show that it allows the following code block to not leak memory at all: { my $textview = Gtk2::TextView->new(); my $wrapmode = $textview->get_wrap_mode(); my $buffer = $textview->get_buffer(); my $bounds = $buffer->get_bounds(); my $button = Gtk2::Button->new_with_label('hello!'); my $vbox = Gtk2::VBox->new(0, 0); $vbox->pack_start(Gtk2::ProgressBar->new(), 0, 0, 0); $vbox->pack_start($button, 0, 0, 0); $vbox->pack_start($textview, 0, 0, 0); my $window = Gtk2::Window->new('toplevel'); $window->add($vbox); my $style = Gtk2::Style->new(); $style->unref(); my $color = Gtk2::Gdk::Color->new(150*256, 250*256, 0); my $color2 = Gtk2::Gdk::Color->parse('blue'); } Please tell me if it's ok for you, then I'd commit. Thanks, Ref: [1] reading docs/refcounting.txt from the gtk+ sources helped a lot [2] in a perl block, you create a GtkWindow and add it a GtkFrame; when the perl destructors are called, you don't know in which order they will be; if the perl destructor of the window is called first, it calls gtk_widget_destroy, and gtk also destroys the add'ed frame; then when the perl destructor of the frame gets called, you can't even test to see if it's a floating object since it has already been freed up when the window has been destroyed (testing gives a glib warning log); so to implement that, we'd require much trick which are not worth the worry IMHO (the trick could be to add code when we container_add and box_pack to flag the associated widgets for being ignored when later destroyed, for example) -- Guillaume Cottenceau - http://people.mandrakesoft.com/~gc/