为什么我的 GTK+ 信号回调中出现分段错误?
Why do I get a segmentation fault in my GTK+ signal callback?
我正在尝试测量 GTK 标签的大小:
#include <gtk/gtk.h>
static void map_event(GtkWidget *window, gpointer lab) {
g_print( "In the callback..\n" );
GtkWidget *label = GTK_WIDGET(lab);
g_print( "Everything is ok..\n" );
}
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 280);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label = gtk_label_new("Hello world!");
gtk_grid_attach(GTK_GRID (grid), label, 0,0,1,1);
g_signal_connect (window, "map-event", G_CALLBACK(map_event), label);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new (
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
这给出了输出:
In the callback..
Segmentation fault (core dumped)
如果我注释掉这一行:
GtkWidget *label = GTK_WIDGET(lab);
没有分段错误,标签出现,输出为:
In the callback..
Everything is ok..
我在这里错过了什么?
map-event
具有以下签名,因此您缺少 GdkEvent*
参数:
gboolean
user_function (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
不幸的是,GTK+是用C写的,所以它缺少类型安全的回调函数,所以很容易犯这样的错误。
您不尊重信号签名。每个信号都与一个预定义的函数原型相关联,您 必须 遵守,否则您只会阅读垃圾。在这里,您只是胡乱编造了回调签名,所以事情不会按预期工作。
信号就像美味的水果送货服务。通过连接到该信号,您签署了一份订阅水果送货服务的合同。水果只有在水果成熟时才会交付。送货员将:
- 来到你家门前
- 送你几个水果盒
- 敲你的门
- 回到卡车上
合同还规定:
- 盒子 #1 将包含香蕉
- 盒子 #2 将包含苹果
- 盒子 #3 将包含橙子
这些框就像您的回调参数。 map-event 有 3 个参数,因此有 3 个框。
有一天,你听到敲门声。你打开门,看到箱子,打开箱子 #2,然后生气地说 "damn, I said I wanted oranges!"。问题是你在混合苹果和橘子:根据合同,橘子在#3 盒子里,你在#2 盒子里找。
因此请查看您要连接的每个信号的文档。这是编写正确回调的唯一方法。这里您忘记了一个输入参数以及 return 值。在 map-event
的情况下,可以看到 return 值,因为你要去卡车上说你是想继续还是停止交付。
我正在尝试测量 GTK 标签的大小:
#include <gtk/gtk.h>
static void map_event(GtkWidget *window, gpointer lab) {
g_print( "In the callback..\n" );
GtkWidget *label = GTK_WIDGET(lab);
g_print( "Everything is ok..\n" );
}
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 280);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label = gtk_label_new("Hello world!");
gtk_grid_attach(GTK_GRID (grid), label, 0,0,1,1);
g_signal_connect (window, "map-event", G_CALLBACK(map_event), label);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new (
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
这给出了输出:
In the callback..
Segmentation fault (core dumped)
如果我注释掉这一行:
GtkWidget *label = GTK_WIDGET(lab);
没有分段错误,标签出现,输出为:
In the callback..
Everything is ok..
我在这里错过了什么?
map-event
具有以下签名,因此您缺少 GdkEvent*
参数:
gboolean
user_function (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
不幸的是,GTK+是用C写的,所以它缺少类型安全的回调函数,所以很容易犯这样的错误。
您不尊重信号签名。每个信号都与一个预定义的函数原型相关联,您 必须 遵守,否则您只会阅读垃圾。在这里,您只是胡乱编造了回调签名,所以事情不会按预期工作。
信号就像美味的水果送货服务。通过连接到该信号,您签署了一份订阅水果送货服务的合同。水果只有在水果成熟时才会交付。送货员将:
- 来到你家门前
- 送你几个水果盒
- 敲你的门
- 回到卡车上
合同还规定:
- 盒子 #1 将包含香蕉
- 盒子 #2 将包含苹果
- 盒子 #3 将包含橙子
这些框就像您的回调参数。 map-event 有 3 个参数,因此有 3 个框。
有一天,你听到敲门声。你打开门,看到箱子,打开箱子 #2,然后生气地说 "damn, I said I wanted oranges!"。问题是你在混合苹果和橘子:根据合同,橘子在#3 盒子里,你在#2 盒子里找。
因此请查看您要连接的每个信号的文档。这是编写正确回调的唯一方法。这里您忘记了一个输入参数以及 return 值。在 map-event
的情况下,可以看到 return 值,因为你要去卡车上说你是想继续还是停止交付。