单击 GtkButton 时出现分段错误

segmentation fault on clicking a GtkButton

根据我程序中 init_prog(user) 调用的位置,我遇到了分段错误,我不明白原因。如果我在单击 btn_go 后将调用放在 start() 回调函数中,它会崩溃:

Thread 1 "./a.out" received signal SIGSEGV, Segmentation fault. 0x00007ffff7812526 in gdk_window_get_display (window=0x55555555b1c0) at ../../../../gdk/gdkwindow.c:2303 2303 ../../../../gdk/gdkwindow.c: No such file or directory.

这是回溯:

Thread 1 "./a.out" received signal SIGSEGV, Segmentation fault.
0x00007ffff7812526 in gdk_window_get_display (window=0x55555555b1c0) at ../../../../gdk/gdkwindow.c:2303
2303    ../../../../gdk/gdkwindow.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7812526 in gdk_window_get_display (window=0x55555555b1c0) at ../../../../gdk/gdkwindow.c:2303
#1  0x00007ffff78022ce in event_get_display (event=0x7fffe800add0) at ../../../../gdk/gdkevents.c:457
#2  0x00007ffff78022ce in gdk_event_free (event=0x7fffe800add0) at ../../../../gdk/gdkevents.c:839
#3  0x00007ffff783311a in gdk_event_source_dispatch
    (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>)
    at ../../../../../gdk/x11/gdkeventsource.c:369
#4  0x00007ffff730cf2e in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#5  0x00007ffff730d1c8 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#6  0x00007ffff730d4c2 in g_main_loop_run () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#7  0x00007ffff7affb15 in gtk_main () at ../../../../gtk/gtkmain.c:1323
#8  0x0000555555556da1 in create_window () at gui.c:118
#9  0x000055555555644d in main (argc=1, argv=0x7fffffffe328) at main.c:26

这是代码:

#include <glib.h>
#include <stdio.h>
#include <gtk/gtk.h>

void start (GtkWidget *widget, struct prog_data *user);

void create_window() {

    GtkWidget *window;
    GtkWidget *headbar;
    GtkWidget *vbox;
    GtkWidget *hbox_superself;
    GtkWidget *hbox_my_struct;
    GtkWidget *hbox_self;
    GtkWidget *btn_about;
    GtkWidget *btn_go;
    GtkWidget *evnt_box[3];

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    headbar = gtk_header_bar_new();
    btn_about = gtk_button_new_with_label("About");
    btn_go = gtk_button_new_with_label("Start");
    evnt_box[0] = gtk_evnt_box_new ();
    evnt_box[1] = gtk_evnt_box_new ();
    evnt_box[2] = gtk_evnt_box_new ();
    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    hbox_superself = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 35);
    hbox_my_struct = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
    hbox_self = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 35);
    my_struct.label_user[USR0] = gtk_label_new ("0");
    my_struct.label_user[USR1] = gtk_label_new ("0");
    my_struct.lbl_pings_left = gtk_label_new ("");

    my_struct.img_show[0] = gtk_image_new ();
    my_struct.img_show[1] = gtk_image_new ();

    my_struct.image_deck_pile = gtk_image_new_from_file ("1.png");

my_struct.self_image[0] = gtk_image_new_from_file ("2.png");
my_struct.self_image[1] = gtk_image_new_from_file ("2.png");
my_struct.self_image[2] = gtk_image_new_from_file ("2.png");

    my_struct.image_orca = gtk_image_new ();

    my_struct.super_self[0] = gtk_image_new();
    my_struct.super_self[1] = gtk_image_new();
    my_struct.super_self[2] = gtk_image_new();

    gtk_header_bar_set_title (GTK_HEADER_BAR (headbar), "Orca");
    gtk_window_set_title (GTK_WINDOW (window), "Orca");    
    gtk_window_set_titlebar (GTK_WINDOW (window), headbar);
    gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (headbar), TRUE);
    gtk_window_maximize (GTK_WINDOW (window));

    GtkCssProvider *css_provider = gtk_css_provider_new();
    gtk_css_provider_load_from_path (css_provider, "style.css", NULL);

    GdkScreen *myScreen = gdk_screen_get_default();
    gtk_style_context_add_provider_for_screen (myScreen, GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER);

    struct prog_data user[2];

    gtk_container_add(GTK_CONTAINER (headbar), btn_about);
    gtk_container_add(GTK_CONTAINER (window), vbox);
    gtk_container_add(GTK_CONTAINER (vbox), hbox_superself);
    gtk_container_add(GTK_CONTAINER (vbox), hbox_my_struct);
    gtk_container_add(GTK_CONTAINER (vbox), hbox_self);
    gtk_container_add(GTK_CONTAINER (hbox_superself), my_struct.self_image[0]);
    gtk_container_add(GTK_CONTAINER (hbox_superself), my_struct.self_image[1]);
    gtk_container_add(GTK_CONTAINER (hbox_superself), my_struct.self_image[2]);
    gtk_container_add(GTK_CONTAINER (hbox_superself), my_struct.label_user[USR1]);
    gtk_container_add(GTK_CONTAINER (hbox_my_struct), my_struct.image_orca);
    gtk_container_add(GTK_CONTAINER (hbox_my_struct), my_struct.image_deck_pile);
    gtk_container_add(GTK_CONTAINER (hbox_my_struct), my_struct.lbl_pings_left);
    gtk_container_add(GTK_CONTAINER (hbox_my_struct), btn_go);
    gtk_container_add(GTK_CONTAINER (hbox_my_struct), my_struct.img_show[0]);
    gtk_container_add(GTK_CONTAINER (hbox_my_struct), my_struct.img_show[1]);
    gtk_container_add(GTK_CONTAINER (hbox_self), evnt_box[0]);
    gtk_container_add(GTK_CONTAINER (hbox_self), evnt_box[1]);
    gtk_container_add(GTK_CONTAINER (hbox_self), evnt_box[2]);
    gtk_container_add(GTK_CONTAINER (evnt_box[0]), my_struct.super_self[0]);
    gtk_container_add(GTK_CONTAINER (evnt_box[1]), my_struct.super_self[1]);
    gtk_container_add(GTK_CONTAINER (evnt_box[2]), my_struct.super_self[2]);
    gtk_container_add(GTK_CONTAINER (hbox_self), my_struct.label_user[USR0]);

    GtkStyleContext *context1;                                      
    context1 = gtk_widget_get_style_context(hbox_self);         
    gtk_style_context_add_class(context1, "my_hbox_self");

    GtkStyleContext *context2;
    context2 = gtk_widget_get_style_context(hbox_superself);    
    gtk_style_context_add_class(context2, "my_hbox_superself");

    GtkStyleContext *context3;
    context3 = gtk_widget_get_style_context(hbox_my_struct);    
    gtk_style_context_add_class(context3, "my_hbox_my_struct");

    gtk_widget_set_name (my_struct.img_show[0], "user1");

    g_signal_connect (btn_about, "clicked", G_CALLBACK (activate_about), NULL);
    g_signal_connect (G_OBJECT (evnt_box[0]), "button_press_event", G_CALLBACK (ping1_clicked), user);
    g_signal_connect (G_OBJECT (evnt_box[1]), "button_press_event", G_CALLBACK (ping2_clicked), user);
    g_signal_connect (G_OBJECT (evnt_box[2]), "button_press_event", G_CALLBACK (ping3_clicked), user);
    g_signal_connect (G_OBJECT (btn_go), "button_press_event", G_CALLBACK (start), user);
    g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL);

    gtk_widget_show_all (window);

    gtk_main();
}

void start (GtkWidget *btn_go, struct prog_data *user) {
    gtk_widget_hide(btn_go);
    printf("Right\n");
    init_prog(user);    
}

如果我在 create_window() 函数中将调用 init_prog(user) 移动到 gtk_widget_show_all (window); 之后,我不会遇到任何崩溃。我单独测试了 init_prot(user) 函数,它运行良好。

您通过提供不正确的回调函数来欺骗 GTK。

The manual 告诉我们您的回调在 "button_press_event":

中的样子
gboolean
user_function (GtkWidget *widget,
               GdkEvent  *event,
               gpointer   user_data)

您访问 event 指针并将其视为 user_data 指针。这会导致未定义的行为。 您也未能提供强制布尔值 return 值。

您必须调整回调函数的签名以满足要求。

或者您可能会改为使用按钮小部件的 "clicked""pressed" 事件,而不是 "button-pressed-event"

您还应检查问题中未出现的其他回调函数是否存在相同错误。