2012-06-01 12 views
6

Para probar mi comprensión de otros bits de Gtk, me gustaría escribir un programa que siempre tenga un evento listo para que el bucle principal consuma. Escribí este programa corto para intentar hacer esto:segfault al tratar de mantener el bucle principal ocupado

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

Cuando ejecuto este programa y hago clic en la casilla de verificación, segfaults. ¿Lo que da? ¿Cuál es la forma correcta de mantener ocupado el bucle principal?

(Nota al margen: se conmuta de forma fiable 2048 veces antes de violación de segmento - un número redondo con recelo.)

+0

ejecutarlo a través de un depurador y tratar de conseguir una traza, probablemente las señales se enviaron sincrónicamente, y obtendrá un desbordamiento de pila. – nos

+0

@nos Un desbordamiento de pila que pude entender (porque, como dices, las señales parecen despacharse sincrónicamente), pero ese no es el comportamiento que veo. –

+0

@nos Disculpas; después de un poco de Google, parece desbordar la pila puede causar una segfault. ¡Gracias! –

Respuesta

7

Dentro de su manejador toggle, se está configurando checked, lo que provoca una señal toggle a ser emitida, que re- invoca el manejador ...

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

no seguí hasta el fondo, pero puedo ver cómo> 11000 marcos dará lugar a una violación de segmento.

para responder a su otra pregunta: Creo que la manera de mantener el bucle principal completa sería con un g_idle_add() llamada:

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