分段故障GTK +应用程序

时间:2015-05-31 22:33:57

标签: c segmentation-fault gtk glade

我正在使用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-&gt; 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);                                                                                                                                                
}

我在这里得到了一个Segfault,但我不知道为什么......:

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,它会崩溃同样的事情。 提前谢谢!!

2 个答案:

答案 0 :(得分:2)

我发现了问题。 在我的处理函数中,我们需要传入参数,即我们单击的小部件的类型。在这里,它是一个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需要它在后台。所以它已经解决了。 无论如何,谢谢你的帮助! :)

答案 1 :(得分:0)

Valgrind在这里对你没什么帮助。删除.oexecutable,重新编译将-g-O0添加到编译命令。

然后运行gdb,并在发生分段错误时执行backtrace。你应该能够解决问题所在。 (在这里发布回溯)

你在跑步过程中看到了什么消息吗?甚至警告?