g_object_ref_sink() replaces gtk_object_sink() Please make this substitution
James, On Thu, 2008-02-28 at 00:04 -0500, James Scott Jr wrote: > On Wed, 2008-02-27 at 21:03 -0500, Mark Rodriguez wrote: > > > James, > > > > > When doe s the error occur? > > > 0. When program starts > > > 1. When shutting down > > > 2. When creating the text_view the first time > > > 3. When creating the text_view the Nth time > > > > > > I will assume it happens durin shutdown (#1). > > > > Yes you are correct. In the "real" application, the application > > doesn't exit. It destroys the canvas and re-uses it with new controls. > > Rather than debug that [monster], I reduced the application to > > something more manageable that exhibit the same behavior. > > > > > Yes, it should be handled like any other widget. The only special thing > > > is > > > its text_buffer! Consider gtk_text_view_new_with_buffer(), one is created > > > automatically for when using the gtk_text_view_new() api. I don't think > > > creating the GtkTextBuffer first would make any difference -- however, > > > that > > > where you are now. So try creating the GtkTextBuffer first, then use the > > > ...with_buffer() api to create the view. This may produce a different > > > result. > > > > Interesting. I tried a few different things today and was able to get > > the application to work as expected without crashing, but I don't like > > the solution as now it appears I'm leaking memory. Any thoughts on why > > if g_object_unref is called the application complains about the double > > free? I modified the code as follows (mainly the button_click_event > > handler was changed to handle the text buffer and to require clicking > > the 'Quit' button twice for exiting the app - this was just done for > > visibility reasons). > > > > ref's are strange things: When I run into this anomaly I do the > following, reasoning that I must have only had a weak reference, and > g_object_unref got confused -- anyway this normally works for me. > > /* creation code ... */ > ... > buffer = gtk_text_buffer_new(NULL); > if (buffer != NULL) { > g_object_ref (G_OBJECT(buffer)); > gtk_object_sink (G_OBJECT(buffer)); > } > > sinking it ensures that you have a full fledged reference that a later > unref will honor. > > If your creating and deleting this text_view as needed, you will have to > find the root cause of these messages. I notice that you prep'ed the > main() to use threads. Your problem maybe related to how your using > threads when creating/destroying the text view. I would suggest > exploring this type of change. > > 1a. Only create/destroy in the main gtk/gdk thread. > > 1b. Fire off a g_timeout_add( 500000, (GSourceFunc)fn_create_routine(), > gpointer); where "gboolean fn_create_routine(gpointer gp);" calls the > normal gtk_window_new() stuff to create a dialog or the window you plan > to use the text_view in. All this gets you out of the normal gtk signal > chain of events. signals iterate on themselves and I've seen unwinds > cause random errors - like your double-free. > > 1c. Do essentially the same to destroy the window. > > 2a. I guess I don't actually delete/destroy main windows once created, I > just hide them and present them again when needed. > 2b. Or if I do destroy them, i keep the buffer and/or tree_model in a > allocated memory structure. Thus gtk_text_view_new_with_buffer() is the > type of call I most often use to create text_views. > > 3. You seem to be _show() ing objects before adding them to something. > Look at vbox; you create it, show it, then add it to the main.window. > The recommended style is to create, add, show. I don't think causes > any immediate problems but it could be polluting something- anyway this > strikes me as something worth cleaning up. > > > James, > > > > > > [code] > > GtkWidget *main_window, *text_view, *box, *button; > > GtkTextBuffer* buffer; > > > > static void destroy_event(GtkWidget* widget, void* data) > > { > > gtk_main_quit(); > > } > > > > static void button_click_event(void) > > { > > if (text_view != NULL) > > { > > gtk_container_remove(GTK_CONTAINER(box), text_view); > > text_view = NULL; > > // leaking memory??? > > // g_object_unref(G_OBJECT(buffer)); > > buffer = NULL; > > } > > else > > { > > gtk_widget_destroy(main_window); > > main_window = NULL; > > } > > } > > > > int main(int argc, char* argv[]) > > { > > // initialize multi-threading within GLib > > g_thread_init(NULL); > > > > // initialize multi-threading within GDK > > gdk_threads_init(); > > > > // acquire thread lock > > gdk_threads_enter(); > > gtk_init(&argc, &argv); > > > > // create main window > > main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); > > if (main_window == NULL) > > abort(); > > g_signal_connect(G_OBJECT(main_window), "destroy", > > G_CALLBACK(destroy_event), NULL); > > gtk_widget_show(main_window); > > > > box = gtk_vbox_new(FALSE, 5); > > if (box == NULL) > > abort(); > > gtk_widget_show(box); > > gtk_container_add(GTK_CONTAINER(main_window), box); > > > > buffer = gtk_text_buffer_new(NULL); > > if (buffer == NULL) > > abort(); > > > > text_view = gtk_text_view_new_with_buffer(buffer); > > if (text_view == NULL) > > abort(); > > gtk_widget_show(text_view); > > gtk_box_pack_start(GTK_BOX(box), text_view, TRUE, TRUE, 5); > > > > button = gtk_button_new_with_label("Quit"); > > if (button == NULL) > > abort(); > > g_signal_connect(G_OBJECT(button), "clicked", > > G_CALLBACK(button_click_event), NULL); > > gtk_widget_show(button); > > gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 5); > > > > // run the main loop > > gtk_main(); > > > > // release thread lock > > gdk_threads_leave(); > > > > return 0; > > } > > [/code] > > > > > _______________________________________________ > gtk-app-devel-list mailing list > gtk-app-devel-list@gnome.org > http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list