LINUX.ORG.RU

В чем причина сегфолта?

 , ,


0

1

Если собрать софт так:

meson builddir --prefix=/usr && cd builddir && ninja
то работает нормально, никаких сегфолтов нет. Если собрать rpm или flatpak, то сегфолтится на строке prop_changed (p):
public signal void prop_changed (bool state);


if (prop.format == Format.FLAG) {
	int i = *(int*) ( ( (EventProperty<int>) prop).data);
	bool p = (i == 0) ? false : true;
	prop_changed (p); // Emit signal
}
Эквивалентный сгенерированный кусок на Си:
if (prop->format == FORMAT_FLAG) {
	gint i = 0;
	gboolean p = FALSE;
	i = *((gint*) ((gint) ((gintptr) ((struct event_property*) prop)->data)));
	if (i == 0) {
		p = FALSE;
	} else {
		p = TRUE;
	}
	g_signal_emit (self, prg_signals[PROP_CHANGED_SIGNAL], 0, p);
}
Если строку заменить на prop_changed (false), то сегфолт пропадает. Подскажите, что не так.
(gdb) run
Thread 1 "com.gitlab.prg" received signal SIGSEGV, Segmentation fault.
0x0000555555560c49 in event_handler (self=0x555555b7f340) at src/src@@com.gitlab.prg@exe/prg.c:581
581						g_signal_emit (self, prg_signals[PROP_CHANGED_SIGNAL], 0, _tmp31_);
(gdb) bt
#0  0x0000555555560c49 in prg_event_handler (self=0x555555c17330)
    at src/src@@com.gitlab.prg@exe/prg.c:581
#1  0x00007ffff7cc81cb in g_idle_dispatch () at /lib64/libglib-2.0.so.0
#2  0x00007ffff7ccb88d in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#3  0x00007ffff7ccbc58 in g_main_context_iterate.isra () at /lib64/libglib-2.0.so.0
#4  0x00007ffff7ccbcf0 in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#5  0x00007ffff7980725 in g_application_run () at /lib64/libgio-2.0.so.0
#6  0x000055555555a211 in _vala_main (args=0x7fffffffd6e8, args_length1=1) at src/src@@com.gitlab.prg@exe/main.c:67
#7  0x00007ffff5ff2413 in __libc_start_main () at /lib64/libc.so.6
#8  0x000055555555a0ce in _start () at src/src@@com.gitlab.prg@exe/main.c:77

★★

i = *((gint*) ((gint) ((gintptr) ((struct event_property*) prop)->data)));
int i = *(int*) ( ( (EventProperty<int>) prop).data);

Это жесть вообще. Ты берёшь 64-битный указатель, преобразуешь его в 64-битное целое, затем обрезаешь его 32-битного целого, затем преобразуешь в указатель на gint, который потом разыменовываешь. Ты испортил указатель, причём не случайно по недочёту в разнесённых частях программы. Ты прямо в одной строчке это делаешь.

Зачем?

i-rinat ★★★★★ ()
Ответ на: комментарий от i-rinat

Так я и пытаюсь его использовать. prop->data типа void*, я говорю, что это int* и разименовываю * (int*). Как правильно то?

int i = *(int*) ( ( (EventProperty<int>) prop).data);
prinf(i=%d, i);

В сборке, которая не сегфолтится, показывает либо 0, либо 1. Как и должно быть.

nvl ★★ ()
Последнее исправление: nvl (всего исправлений: 1)
Ответ на: комментарий от i-rinat

Исправил

int i = *(int*) ( ( (EventProperty<int>) prop).data);
на
int i = *(int*) ( ( (EventProperty<void>) prop).data);
Эквивалентная строка на Си сгенерировалась так:
i = *( (gint*) ( (struct event_property*) prop)->data);

Больше не сегфолтится. Спасибо.

nvl ★★ ()
Ответ на: комментарий от nvl

Vala ведь создавалась для работы с GObject, GLib и Gtk? Всякие свойста, передача параметров в сигналы это там очень распространённые операции. Странно, что в коде на Vala нужно так извращаться. Ты уверен, что там более простого способа нет? Твой подход — жутко костыльный и очень опасный.

i-rinat ★★★★★ ()
Ответ на: комментарий от i-rinat

Да, там все просто. Это извращение нужно, т.к. приходится использовать стороннюю библиотеку на c++. Собственно это единственное место, где приходится извращаться с указателями.

nvl ★★ ()