在简单的GTK +应用程序中启用优化时出现分段错误?

gat*_*ich 5 c gtk 64-bit null segmentation-fault

可能是为时已晚,但我发现至少好奇以下几行似乎导致了分段错误,当且仅当使用gcc的优化编译时,甚至是"-O1"!

settings_dialog = gtk_dialog_new_with_buttons("gatotray Settings"
    , NULL, 0, GTK_STOCK_CANCEL, FALSE, GTK_STOCK_SAVE, TRUE, 0);
g_signal_connect(G_OBJECT(settings_dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL);
g_signal_connect(G_OBJECT(settings_dialog), "destroy", G_CALLBACK(settings_destroyed), NULL);
GtkWidget *vb = gtk_dialog_get_content_area(GTK_DIALOG(settings_dialog));
GtkWidget *hb = gtk_hbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(hb), gtk_label_new("Background:"));
GtkWidget *cb = gtk_color_button_new();
gtk_container_add(GTK_CONTAINER(hb), cb);
gtk_container_add(GTK_CONTAINER(vb), hb);
Run Code Online (Sandbox Code Playgroud)

这是回溯:

(gdb) backtrace 
#0  0x00007ffff4d88052 in ?? () from /lib/libc.so.6
#1  0x00007ffff5304112 in g_strdup () from /lib/libglib-2.0.so.0
#2  0x00007ffff5bc799d in ?? () from /usr/lib/libgobject-2.0.so.0
#3  0x00007ffff5ba826c in g_object_new_valist ()
   from /usr/lib/libgobject-2.0.so.0
#4  0x00007ffff5ba84f1 in g_object_new () from /usr/lib/libgobject-2.0.so.0
#5  0x00007ffff78502d5 in gtk_button_new_from_stock ()
   from /usr/lib/libgtk-x11-2.0.so.0
#6  0x00007ffff787cc95 in gtk_dialog_add_button ()
   from /usr/lib/libgtk-x11-2.0.so.0
#7  0x00007ffff787cd60 in ?? () from /usr/lib/libgtk-x11-2.0.so.0
#8  0x00007ffff787cf60 in gtk_dialog_new_with_buttons ()
   from /usr/lib/libgtk-x11-2.0.so.0
#9  0x0000000000402bb9 in show_settings_dialog () at settings.c:24
#10 0x0000000000403328 in main (argc=1, argv=0x7fffffffe2b8) at gatotray.c:286
Run Code Online (Sandbox Code Playgroud)

... settings.c:24正是上面列出的第一行,似乎"gtk_dialog_new_with_buttons"是罪魁祸首......

版本:
gcc:4.4.3
GTK +:2.20.1

顺便说一句,忘记提及在冲突呼叫阻止它发生评论某些行.特别是"gtk_container_add(GTK_CONTAINER(hb),cb);"

我尝试了几乎所有合适的GtkTypes/GTK_MACROS组合,它没有任何区别.

gat*_*ich 3

长话短说:当手册说NULL时使用NULL,而不是普通的0

\n\n

(由于我无法选择评论作为答案,所以我自己写答案,感谢有帮助的评论......)

\n\n

GTK+ 文档指出:

\n\n
GtkWidget*\ngtk_dialog_new_with_buttons (const gchar    *title,\n                             GtkWindow      *parent,\n                             GtkDialogFlags  flags,\n                             const gchar    *first_button_text,\n                         ...);\n\ntitle\xc2\xa0: Title of the dialog, or NULL. allow-none.\nparent\xc2\xa0: Transient parent of the dialog, or NULL. allow-none.\nflags\xc2\xa0: from GtkDialogFlags\nfirst_button_text\xc2\xa0: stock ID or text to go in first button, or NULL. allow-none.\n...\xc2\xa0: response ID for first button, then additional buttons, ending with NULL\n
Run Code Online (Sandbox Code Playgroud)\n\n

但那天晚上我很懒,只在预期为 NULL 的地方输入了“0”:

\n\n
settings_dialog = GTK_DIALOG(gtk_dialog_new_with_buttons("gatotray Settings"\n    , NULL, 0, GTK_STOCK_CANCEL, FALSE, GTK_STOCK_SAVE, TRUE, 0));\n
Run Code Online (Sandbox Code Playgroud)\n\n

...没有注意到 NULL 是一个指针,在我的 64 位系统中是 64 位宽,而 0 是一个 32 位整数...

\n\n

另外,似乎在变量参数列表中,编译器无法检测到不一致之处:使用 -Wall 悄悄编译的代码。

\n\n

正如Myforwik所建议的和Havoc P进一步澄清的那样,使用“NULL”而不是“0”解决了这个问题。多谢你们!

\n\n

作为记录,我在 32 位模式下进行了测试编译,其中 NULL 也是 32 位,在这种情况下没有段错误。但它仍然是不正确的,因为文档已经足够清楚了,并且 NULL 不是 0,无论 C++ 委员会成员怎么说!;-)

\n

  • 这里的关键*问题*是变量参数列表 - C 编译器会将任何文字“0”转换为“NULL”指针**当它知道**你需要一个指针时 - 并且它不能(必然)知道编译可变参数调用时! (3认同)