Frage segfault, wenn versucht wird, die Hauptschleife besetzt zu halten


Um mein Verständnis anderer Bits von Gtk zu testen, möchte ich ein Programm schreiben, das immer ein Ereignis bereithält, das die Hauptschleife konsumieren kann. Ich habe dieses kurze Programm geschrieben, um dies zu versuchen:

#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();
}

Wenn ich dieses Programm ausführe und auf das Kontrollkästchen klicke, werden die Standardwerte zurückgesetzt. Was gibt? Was ist der richtige Weg, um die Hauptschleife beschäftigt zu halten?

(Randbemerkung: Es schaltet zuverlässig 2048 Mal vor dem Segfaulting ein - eine verdächtig runde Zahl.)


6
2018-06-01 21:47


Ursprung


Antworten:


In deinem toggle Handler, du stellst ein checked, die a verursacht toggle zu sendendes Signal, das den Handler erneut aufruft ...

#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 ()

Ich bin nicht den ganzen Weg nach unten gegangen, aber ich kann sehen, wie> 11000 Frames zu einem Segfault führen.

Um Ihre andere Frage zu beantworten: Ich denke, der Weg, um die Hauptschleife voll zu halten, wäre mit einem g_idle_add() Anruf:

#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();
}

7
2018-06-01 22:01