【问题标题】:Segmentation Fault GTK+ application [duplicate]分段故障 GTK+ 应用程序 [重复]
【发布时间】:2015-05-31 22:33:56
【问题描述】:

我正在使用 Glade 制作 GTK 3+ 应用程序。 这是我在 C 中的结构:

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

typedef struct  s_gtk                                                                                                                                                             
{                                                                                                                                                                                 
  GtkBuilder    *interface;                                                                                                                                                       
  GtkWidget     *MainWindow;                                                                                                                                                      
  GtkWidget     *AddObject;                                                                                                                                                       
  GtkWidget     *DeleteObject;                                                                                                                                                    
  GtkWidget     *Launch;                                                                                                                                                          
  GError        *error;                                                                                                                                                           
  gchar         *filename;                                                                                                                                                        
}               t_gtk;

我的 gtk->AddObject 初始化函数,在 main 中调用:

    if ((gtk->interface = gtk_builder_new()) == NULL ||                                                                                                                             
      (gtk->filename = g_build_filename("interface.glade", NULL)) == NULL)                                                                                                        
    {                                                                                                                                                                             
      g_error("%s", gtk->error->message);                                                                                                                                         
      g_error_free(gtk->error);                                                                                                                                                   
      return (gtk->error->code);                                                                                                                                                  
    }                                                                                                                                                                             
  gtk_builder_add_from_file(gtk->interface, gtk->filename, &gtk->error);                                                                                                          
  g_free(gtk->filename);                                                                                                                                                          
  if (gtk->error)                                                                                                                                                                 
    {                                                                                                                                                                             
      g_printerr("%s\n", gtk->error->message);                                                                                                                                    
      g_error_free(gtk->error);                                                                                                                                                   
      return (gtk->error->code);                                                                                                                                                  
    }                                                                                                                                                                             
  gtk->MainWindow = GTK_WIDGET(gtk_builder_get_object                                                                                                                             
                              (gtk->interface, "MainWindow"));                                                                                                                    
  gtk->AddObject = GTK_WIDGET(gtk_builder_get_object                                                                                                                              
                             (gtk->interface, "AddDialog"));                                                                                                                      
  gtk_builder_connect_signals(gtk->interface, gtk);                                                                                                                               
  return (0);

我的 AddObject 处理程序:

void            on_AddObject_clicked(gpointer user_data)                                                                                                                          
{                                                                                                                                                                                 
  t_gtk         *gtk;                                                                                                                                                             
  gint          response;                                                                                                                                                         

  gtk = (t_gtk *)user_data;                                                                                                                                                       
  printf("I'm here\n");                                                                                                                                                           
  response = gtk_dialog_run(GTK_DIALOG(gtk->AddObject));                                                                                                                          
  printf("I'm here2\n");                                                                                                                                                          
  if (response == 1)                                                                                                                                                              
    {                                                                                                                                                                             
      printf("Add pressed!\n");                                                                                                                                                   
    }                                                                                                                                                                             
  else                                                                                                                                                                            
    {                                                                                                                                                                             
      printf("Cancel pressed!\n");                                                                                                                                                
    }                                                                                                                                                                             
  gtk_widget_hide(gtk->AddObject);                                                                                                                                                
}

我在这里遇到了段错误,但我不知道为什么......:

response = gtk_dialog_run(GTK_DIALOG(gtk->AddObject));    

Valgrind 这么说:

Invalid read of size 8
==7272==    at 0x6B16620: g_type_check_instance_cast (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x401063: on_AddObject_clicked (in /home/vives_j/Documents/Epitech/Tests/main)
==7272==    by 0x6AF3473: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D086: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D9DE: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x4F3CA1C: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.1400.5)
==7272==    by 0x4F3CA74: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.1400.5)
==7272==    by 0x6AF3473: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D086: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D9DE: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x4F3A9FF: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.1400.5)
==7272==    by 0xB795DBF: ffi_call_unix64 (in /usr/lib/x86_64-linux-gnu/libffi.so.6.0.2)
==7272==  Address 0x400000003 is not stack'd, malloc'd or (recently) free'd
==7272== 
==7272== 
==7272== Process terminating with default action of signal 11 (SIGSEGV)
==7272==  Access not within mapped region at address 0x400000003
==7272==    at 0x6B16620: g_type_check_instance_cast (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x401063: on_AddObject_clicked (in /home/vives_j/Documents/Epitech/Tests/main)
==7272==    by 0x6AF3473: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D086: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D9DE: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x4F3CA1C: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.1400.5)
==7272==    by 0x4F3CA74: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.1400.5)
==7272==    by 0x6AF3473: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D086: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x6B0D9DE: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1)
==7272==    by 0x4F3A9FF: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.1400.5)
==7272==    by 0xB795DBF: ffi_call_unix64 (in /usr/lib/x86_64-linux-gnu/libffi.so.6.0.2)
==7272==  If you believe this happened as a result of a stack
==7272==  overflow in your program's main thread (unlikely but
==7272==  possible), you can try to increase the size of the
==7272==  main thread stack using the --main-stacksize= flag.
==7272==  The main thread stack size used in this run was 8388608.

我编译为(来自 make 命令):

gcc -Wextra -Wall -ansi -pedantic -I. -O3 -D REENTRANT -rdynamic -DGTK_DISABLE_DEPRECATED=1 -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DG_DISABLE_DEPRECATED -DGTK_MULTIHEAD_SAFE=1 -DGTK_MULTIDEVICE_SAFE=1 `pkg-config gmodule-export-2.0 --libs` `pkg-config gtk+-3.0 --cflags`   -c -o main.o main.c
gcc main.o -o main `pkg-config gtk+-3.0 --libs` `pkg-config gmodule-export-2.0 --libs`

GDB 结果:

GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./main...done.
(gdb) 
(gdb) run
Starting program: /home/vives_j/Documents/Epitech/Tests/main 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

(process:3752): Gtk-WARNING **: Locale not supported by C library.
    Using the fallback 'C' locale.
[New Thread 0x7fffee33c700 (LWP 3756)]
[New Thread 0x7fffedb3b700 (LWP 3757)]
[New Thread 0x7fffecfe7700 (LWP 3759)]
I'm here

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5f0f620 in g_type_check_instance_cast ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
(gdb) backtrac
#0  0x00007ffff5f0f620 in g_type_check_instance_cast ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#1  0x0000000000401034 in on_AddObject_clicked (user_data=0x8d0350)
    at main.c:57
#2  0x00007ffff5eec474 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#3  0x00007ffff5f06087 in g_signal_emit_valist ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#4  0x00007ffff5f069df in g_signal_emit ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#5  0x00007ffff762ca1d in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#6  0x00007ffff762ca75 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#7  0x00007ffff5eec474 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#8  0x00007ffff5f06087 in g_signal_emit_valist ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#9  0x00007ffff5f069df in g_signal_emit ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#10 0x00007ffff762aa00 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#11 0x00007ffff127edc0 in ffi_call_unix64 ()
   from /usr/lib/x86_64-linux-gnu/libffi.so.6
#12 0x00007ffff127e828 in ffi_call ()
   from /usr/lib/x86_64-linux-gnu/libffi.so.6
---Type <return> to continue, or q <return> to quit---
#13 0x00007ffff5eecebc in g_cclosure_marshal_generic_va ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#14 0x00007ffff5eec474 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#15 0x00007ffff5f06087 in g_signal_emit_valist ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#16 0x00007ffff5f069df in g_signal_emit ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#17 0x00007ffff76cf191 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#18 0x00007ffff5eef233 in g_cclosure_marshal_VOID__BOXEDv ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#19 0x00007ffff5eec474 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#20 0x00007ffff5f06087 in g_signal_emit_valist ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#21 0x00007ffff5f069df in g_signal_emit ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#22 0x00007ffff76cc94e in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#23 0x00007ffff76cdd9b in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#24 0x00007ffff76d05e0 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#25 0x00007ffff76a3e7b in gtk_event_controller_handle_event ()
   from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#26 0x00007ffff783f41d in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
---Type <return> to continue, or q <return> to quit---
#27 0x00007ffff771241e in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#28 0x00007ffff5eec474 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#29 0x00007ffff5f05b30 in g_signal_emit_valist ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#30 0x00007ffff5f069df in g_signal_emit ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#31 0x00007ffff7842de4 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#32 0x00007ffff770fd2e in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#33 0x00007ffff771193e in gtk_main_do_event ()
   from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#34 0x00007ffff72b8b12 in ?? () from /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#35 0x00007ffff5c16c5d in g_main_context_dispatch ()
   from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#36 0x00007ffff5c16f48 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#37 0x00007ffff5c17272 in g_main_loop_run ()
   from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#38 0x00007ffff7710bf5 in gtk_main ()
   from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#39 0x0000000000401275 in main (ac=1, av=0x7fffffffdcf8) at main.c:115
(gdb) quit

第 57 行是我之前发布的崩溃所在的行。

Glade 文件: http://pastebin.com/JrHza6iW 我想我有一个线索。因为,当我从教程中获取这个示例代码时: http://pastebin.com/WpJ6kWQB 并用(及其构建器文件)编译它:

gcc -o dialog1 dialog1.c $(pkg-config --cflags --libs gtk+-2.0 \
 *        gmodule-export-2.0)

它可以工作,但是如果我将 gtk+-2.0 更改为 3.0,它会在同一件事上崩溃。 提前谢谢你!!

【问题讨论】:

    标签: c segmentation-fault gtk glade


    【解决方案1】:

    我发现了问题。 在我的处理函数中,我们需要传入参数我们点击的小部件的类型。在这里,它是一个 GtkButton,所以我将它添加到我收到的参数中:

    void            on_AddObject_clicked(GtkButton *button, gpointer user_data)                                                                                                                          
    {                                                                                                                                                                                 
      t_gtk         *gtk;                                                                                                                                                             
      gint          response;                                                                                                                                                         
    
      gtk = (t_gtk *)user_data;  
      (void) button;                                                                                                                                           
      printf("I'm here\n");                                                                                                                                                           
      response = gtk_dialog_run(GTK_DIALOG(gtk->AddObject));                                                                                                                          
      printf("I'm here2\n");                                                                                                                                                          
      if (response == 1)                                                                                                                                                              
        {                                                                                                                                                                             
          printf("Add pressed!\n");                                                                                                                                                   
        }                                                                                                                                                                             
      else                                                                                                                                                                            
        {                                                                                                                                                                             
          printf("Cancel pressed!\n");                                                                                                                                                
        }                                                                                                                                                                             
      gtk_widget_hide(gtk->AddObject);                                                                                                                                                
    }
    

    我认为 GTK 在后台需要它。所以解决了。 无论如何,谢谢你的帮助! :)

    【讨论】:

      【解决方案2】:

      Valgrind 在这里帮不了你太多。删除.oexecutable,重新编译在编译命令中添加-g-O0

      然后运行gdb,当出现分段错误时,运行backtrace。您应该能够跟踪到问题所在。 (在此处发布回溯)

      您在运行过程中是否看到任何消息?甚至警告?

      【讨论】:

      • 您好,感谢您的快速回复!我用 GDB 结果更新了我的主题。另外,我忘了精确,但是是的,我总是收到警告:Gk-Warning **: Locale not supported by C library。使用后备“C”语言环境。
      • 该警告应该不是问题。回溯有点奇怪,因为错误发生在 gtk 库的深处。而不是在您编写的代码中,而是在“后台”中执行的代码中,而在主循环中参加事件。我对您如何将结构传递给 AddObject 处理程序有一些疑问 - 在 Glade 内部?
      • 我发布了林间空地代码
      • 好吧,我无法进行太多测试,因为我无法编译教程代码(没有 XML 文件),也无法编译您的代码(没有代码)。我将 UI 加载到 Glade 中,并注意到缺少几个小部件(AddDialog 中 Grid 的最后一列,在 MainWindow 中退出后最后打开)。你应该在那里放一些东西——即使只是一个标签)。
      猜你喜欢
      • 2014-07-16
      • 1970-01-01
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      相关资源
      最近更新 更多