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

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]