In order to test my understanding of other bits of Gtk, I would like to write a program which always has an event ready for the main loop to consume. I wrote this short program to try doing this:
#include <gtk/gtk.h>
static void toggle(GtkWidget *check, gpointer data)
{
gboolean checked;
g_object_get(check, "active", &checked, NULL);
g_object_set(check, "active", !checked, NULL);
}
int main(int argc, char *argv[])
{
GtkWidget *window, *check;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
check = gtk_check_button_new();
g_signal_connect(check, "toggled", G_CALLBACK(toggle), NULL);
gtk_container_add(GTK_CONTAINER(window), check);
gtk_widget_show_all(window);
gtk_main();
}
When I run this program and click the check box, it segfaults. What gives? What is the right way to keep the main loop busy?
(Side note: it reliably toggles 2048 times before segfaulting -- a suspiciously round number.)
It can be resolved by having a base condition to return from the recursive function. A pointer must point to valid memory before accessing it.
A segmentation fault (aka segfault) is a common condition that causes programs to crash; they are often associated with a file named core . Segfaults are caused by a program trying to read or write an illegal memory location.
No, memory leaks by themselves would not cause a segmentation fault. However, memory leaks usually indicate sloppy code, and in sloppy code other issues, which would cause a segmentation fault, are likely to be present.
Segmentation faults are a common class of error in programs written in languages like C that provide low-level memory access and few to no safety checks. They arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.
Within your toggle
handler, you're setting checked
, which causes a toggle
signal to be emitted, which re-invokes the handler...
#11564 0xb775ba50 in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0
#11565 0xb776e5d0 in ?? () from /usr/lib/libgobject-2.0.so.0
#11566 0xb77774d6 in g_signal_emit_valist () from /usr/lib/libgobject-2.0.so.0
#11567 0xb7777682 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0
#11568 0xb7e067ba in gtk_toggle_button_toggled ()
I didn't follow all the way down, but I can see how >11000 frames will lead to a segfault.
To answer your other question: I think the way to keep the main loop full would be with a g_idle_add()
call:
#include <gtk/gtk.h>
static void toggle(GtkWidget *check, gpointer data)
{
g_print(".");
}
GtkWidget *window, *check;
static gboolean
toggle_it()
{
gboolean checked;
g_object_get(check, "active", &checked, NULL);
g_object_set(check, "active", !checked, NULL);
return TRUE;
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
check = gtk_check_button_new();
g_signal_connect(check, "toggled", G_CALLBACK(toggle), NULL);
gtk_container_add(GTK_CONTAINER(window), check);
gtk_widget_show_all(window);
g_idle_add((GSourceFunc)toggle_it, NULL);
gtk_main();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With