C 中的 GTK:使用释放键或按键时出现分段错误

GTK in C: Segmentation Fault when using key-release or key-press

对于上下文,我正在尝试制作一个程序来更改程式化标签文本以响应 beaglebone black 上的一些物理输入(例如,如果 high/low 显示此文本,则获取信号)。为了代替我现在无法访问的那些输入,我决定使用按键释放作为替代。

我的代码一直基于这个 combo-box tutorial,它根据组合框选择的文本更改标签文本。我修改了该代码以使用下面代码中的程式化文本。

#include <gtk/gtk.h>

void combo_selected(GtkWidget *widget, gpointer window) {

  gchar *text = g_strjoin(NULL,"<span font='48' weight='bold' color='#DDDDDD'>",gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)),"</span>",NULL); //label text, uses pango markup
  gtk_label_set_markup(GTK_LABEL(window), text);
  g_free(text);
}

int main(int argc, char *argv[]) {

  GtkWidget *window;
  GtkWidget *hbox;
  GtkWidget *vbox;
  GtkWidget *combo;
  GtkWidget *label;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "GtkComboBox");
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_container_set_border_width(GTK_CONTAINER(window), 15);
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);

  hbox = gtk_hbox_new(FALSE, 0);
  vbox = gtk_vbox_new(FALSE, 15);

  combo = gtk_combo_box_new_text();
  gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Ubuntu");
  gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Arch");
  gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Fedora");
  gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Mint");
  gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Gentoo");
  gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Debian");

  gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 0);

  gchar *str = "<span font='48' weight='bold' color='#DDDDDD'>Not Initialized</span>"; //label text, uses pango markup
  label = gtk_label_new(NULL);
  gtk_label_set_markup(GTK_LABEL(label), str); //add pango str to label

  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);

  gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
  gtk_container_add(GTK_CONTAINER(window), hbox);

  g_signal_connect(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), NULL);

  g_signal_connect(G_OBJECT(combo), "changed", 
        G_CALLBACK(combo_selected), (gpointer) label);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

这行得通,但是当尝试使用释放键或按键而不是组合框选项时,出现分段错误。下面是进一步修改后的代码(有些地方被注释掉了)。

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

void fpcheck(GtkWidget *window, gpointer lbl) {
  gchar *text = "<span font='48' weight='bold' color='#DDDDDD'>Press index finger firmly on sensor.</span>";
  gtk_label_set_markup(GTK_LABEL(lbl), text);

  //sleep(2); //placeholder -> fp detection

  //text = "<span font='48' weight='bold' color='#DDDDDD'>Fingerprint recognized!</span>";
  //gtk_label_set_markup(GTK_LABEL(lbl), text);
  g_free(text);
}

int main(int argc, char *argv[]) {

  GtkWidget *window; //main window
  GtkWidget *align; //alignment settings
  GtkWidget *lbl; //text
  GdkColor color = {0, 0x0, 0x0, 0x0}; //window color

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //init window
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); //window pos on screen
  gtk_window_set_default_size(GTK_WINDOW(window), 800, 480); //window size
  //gtk_window_set_resizable(GTK_WINDOW(window), FALSE); //user cant resize
  gtk_window_set_title(GTK_WINDOW(window),"User Display"); //window title
  gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color); //set color to window
  align = gtk_alignment_new(.5,.5,0,0); //x,y alignment
  lbl = gtk_label_new(NULL); //label init

  gchar *str = "<span font='48' weight='bold' color='#DDDDDD'>Not Initialized</span>"; //label text, uses pango markup
  gtk_container_add(GTK_CONTAINER(align), lbl); //add label to alignment
  gtk_container_add(GTK_CONTAINER(window), align); //add label to window
  gtk_label_set_markup(GTK_LABEL(lbl), str); //add pango str to label

  g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(fpcheck), (gpointer) lbl); //calls fpcheck to change label     

  g_signal_connect(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), NULL);

  gtk_widget_show_all(window); //build the window all at once

  gtk_main();

  return 0;
}

如果我在 fpcheck 中注释掉 gtk_label_set_markup 行和 g_free(text) 行,没有错误,但它当然什么也没做。通过查看其他在线资源,我认为此错误是由于 fpcheck 中的第一个参数不正确而试图访问 GTK_LABEL(lbl) 引起的,但这只是一个猜测,我不知道是什么我会放在那里。在示例中,它只是 "Widget," 指的是组合框,我认为,因为它从所选选项中获取文本。

关于这一点,我尝试删除该参数,现在我没有出现分段错误,而是收到以下错误,甚至没有 pressing/releasing。

(test:6698): GLib-GObject-WARNING **: invalid cast from 'GtkWindow' to 'GtkLabel'

(test:6698): Gtk-CRITICAL **: IA__gtk_label_set_markup: assertion 'GTK_IS_LABEL (label)' failed

我做了一些 gdb 回溯,但其中 none 似乎特别有用。如果有人想要他们,我可以 post 他们。

对我遇到的问题有什么想法吗? 谢谢。

key-release-event 处理程序具有此签名

gboolean
user_function (GtkWidget *widget,
               GdkEvent  *event,
               gpointer   user_data)

您的 fpcheck() 需要看起来像那样。

如果你养成这样做的习惯,就更容易及早发现这样的问题。 g_assert (GTK_IS_LABEL (user_data)) 作为每个处理程序中的第一件事,其中用户数据肯定始终必须是标签。