Re: Text View Complaining about Double Free or Corruption



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).

[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]


-- 
Mark



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]