Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

segfault when trying to keep main loop busy

Tags:

c

gtk

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

like image 945
Daniel Wagner Avatar asked Jun 01 '12 21:06

Daniel Wagner


People also ask

How do you resolve a segfault?

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.

What is causing segfault?

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.

Can a memory leak cause a segfault?

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.

What causes a segfault in C?

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.


1 Answers

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();
}
like image 86
gcbenison Avatar answered Sep 25 '22 03:09

gcbenison