GtkWidget*, возвращенный из функции, приводит к ошибке сегментации

Я спрашиваю, почему, если я решу вызвать функцию в другом файле, возвращаемый GtkWidget* вызовет ошибку сегментации, если она используется (приведение, функция gtk, как в примере,...)

Здесь в основном я запускаю gtk_init и пробую GTK_IS_WIDGET из функции, определенной в другом файле.

main.c

#include <gtk/gtk.h>
#include <glib.h>

int main(){
  gtk_init(NULL, NULL);
  GTK_IS_WIDGET(new_widget());
}

Там в другом файле я создаю новый GtkWidget и использую функцию GTK_IS_WIDGET, затем я печатаю «ОК», чтобы узнать, доходит ли выполнение до этого момента.

extern_file.c

#include<gtk/gtk.h>
GtkWidget* new_widget(){
  GtkWidget *new = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  GTK_IS_WIDGET(new);
  g_print("OK\n");
  return new;
}

Я скомпилирую два файла таким образом gcc -o main.o main.c esterno.c $(pkg-config --cflags --libs glib-2.0 gtk+-2.0) Я получаю много предупреждений (которые я поместил туда), но без ошибок.

main.c:6:17: warning: implicit declaration of function ‘new_widget’ [-Wimplicit-function-declaration]
   GTK_IS_WIDGET(new_widget());
                 ^
/usr/include/glib-2.0/gobject/gtype.h:2238:44: note: in definition of macro ‘_G_TYPE_CIT’
   GTypeInstance *__inst = (GTypeInstance*) ip; GType __t = gt; gboolean __r; \
                                            ^~
/usr/include/gtk-2.0/gtk/gtkwidget.h:139:35: note: in expansion of macro ‘G_TYPE_CHECK_INSTANCE_TYPE’
 #define GTK_IS_WIDGET(widget)    (G_TYPE_CHECK_INSTANCE_TYPE ((widget), GTK_TYPE_WIDGET))
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:6:3: note: in expansion of macro ‘GTK_IS_WIDGET’
   GTK_IS_WIDGET(new_widget());
   ^~~~~~~~~~~~~
/usr/include/glib-2.0/gobject/gtype.h:2238:27: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   GTypeInstance *__inst = (GTypeInstance*) ip; GType __t = gt; gboolean __r; \
                           ^
/usr/include/glib-2.0/gobject/gtype.h:495:66: note: in expansion of macro ‘_G_TYPE_CIT’
 #define G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type)            (_G_TYPE_CIT ((instance), (g_type)))
                                                                  ^~~~~~~~~~~
/usr/include/gtk-2.0/gtk/gtkwidget.h:139:35: note: in expansion of macro ‘G_TYPE_CHECK_INSTANCE_TYPE’
 #define GTK_IS_WIDGET(widget)    (G_TYPE_CHECK_INSTANCE_TYPE ((widget), GTK_TYPE_WIDGET))
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:6:3: note: in expansion of macro ‘GTK_IS_WIDGET’
   GTK_IS_WIDGET(new_widget());

Если я запускаю файл (./main.o), я получаю сообщение «ОК», подтверждающее, что GTK_IS_WIDGET внутри функции работает правильно, но затем возникает ошибка сегментации, когда GTK_IS_WIDGET вызывается в main.

Если я объявляю функцию внутри main, все работает нормально, но это не настоящее решение.

заранее спасибо


person Marco Zamboni    schedule 01.03.2019    source источник


Ответы (1)


Я получаю много предупреждений (которые я записал туда), но без ошибок.

Это опасное мышление с C, где любое предупреждение может быть абсолютно фатальным. Я рекомендую использовать -Wall с gcc при разработке (и ослаблять его только в определенных случаях).

В этом случае компилятор предупреждает вас так:

main.c:6:17: warning: implicit declaration of function ‘new_widget’

В C это означает, что при вызове вашей функции используется сигнатура по умолчанию int new_widget(). Ваша фактическая сигнатура функции, конечно, не соответствует этому, поэтому начинают происходить плохие вещи.

Вы можете исправить это, добавив файл заголовка, содержащий правильную сигнатуру функции, и включив этот заголовок в файл main.c.

person Jussi Kukkonen    schedule 02.03.2019
comment
+1 за это: это опасное мышление с C, где любое предупреждение может быть фатальным. Я рекомендую использовать -Wall с gcc при разработке (и расслаблять только в определенных случаях). - person Jman; 04.03.2019