LINUX.ORG.RU

SDL2: Xlib вызывает segfault при работе SDL_Quit

 , , , ,


1

4

имею код:

  7 SDL_Window *window = NULL;
  8 SDL_Surface *screenSurface = NULL;
  9 SDL_Surface *picture = NULL;

...

 43 void shutdown(void) {
 44     SDL_FreeSurface(picture);
 45     picture = NULL;
 46     SDL_DestroyWindow(window);
 47     window = NULL;
 48     SDL_Quit();
 49 }
 50 
 51 int main(int argc, char* args[]) {

...

 55     shutdown();
 56     return 0;
 57 }

Вкратце, весь код отрабатывает безупречно, но при завершении работы программы происходит segfault, когда вызывается SDL_Quit. При отладке gdb показывает, что дело в libX11.so:

X11_VideoQuit (_this=<optimized out>)
    at /home/rustam/src/SDL2-2.0.2/src/video/x11/SDL_x11video.c:651
651	    if (data->im) {
(gdb) 
652	        X11_XCloseIM(data->im);
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6bbbd67 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libX11.so.6

Занятно... погуглил на эту тему и вот эту статью: http://www.remlab.net/op/xlib.shtml

Хочется понять, это я неправильно завершаю программу или Xlib вставляет палки в колеса. Неприятно, когда сегфолты на пустом месте.

Кстати, некоторое время назад этого не происходило, с SDL 1.2 вообще никогда не сталкивался

Буду рад советам

★★★

Последнее исправление: mazdai (всего исправлений: 2)

Зря ты на Xlib батон крошишь. Это что-то самой SDL намудрили.

ref: http://www.libsdl.org/tmp/SDL/src/video/x11/SDL_x11video.c

При вызове X11_VideoInit идёт проверка на #ifdef X_HAVE_UTF8_STRING и if (SDL_X11_HAVE_UTF8) и инициализация data->im.

При вызове X11_VideoQuit только проверка на #ifdef X_HAVE_UTF8_STRING и освобождение data->im.

Не знаю обнуляется ли data в самом начале, но при таком подходе в data->im может быть мусор, что и сегфолтит во втором вызове.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 3)
Ответ на: комментарий от Elyas

Попробуйте описать свои сомнения. Они острые или тянущие? Как долго они продолжаются?

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

Видимо потому, что data->im считается изначально NULL. А берется она из _this. В общем-то можно стопнуться на 651 и попробовать разыменовать data->im, если срау повалится, значит до этого где-то освободили, а если нет, значит сама data->im косячная внутри.

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

может быть. надо проверить

до этого сегфолта не возникало, попробую исходник SDL поправить и обнулить data при вызове

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

не. там валидный адрес. мне кажется, он за границы памяти просто выходит:

    at /home/rustam/src/SDL2-2.0.2/src/video/x11/SDL_x11video.c:651
651	    if (data->im) {
(gdb) print data->im
$1 = (XIM) 0x61e620
(gdb) print 0x61e620
$2 = 6415904
mazdai ★★★
() автор топика
Последнее исправление: mazdai (всего исправлений: 1)
Ответ на: комментарий от arturpub
(gdb) print *(data->im)
$5 = <incomplete type>

чет не то. наверное это мусор

оно при проверке вроде возвращает true, а X11_XCloseIM не может обратиться по этому адресу. щас хакать буду SDL :)

mazdai ★★★
() автор топика

Любитель писать на языках, отличных от раскладки клавиатуры? SDL2 плохо уживается с различными X Input Method.

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

Quick & dirty fix:


--- SDL_x11video.c.orig 2014-06-23 19:54:14.867644797 +0200
+++ SDL_x11video.c      2014-06-23 19:54:55.139652443 +0200
@@ -437,7 +437,7 @@
 
     SDL_free(data->classname);
 #ifdef X_HAVE_UTF8_STRING
-    if (data->im) {
+    if (SDL_X11_HAVE_UTF8 && data->im) {
         X11_XCloseIM(data->im);
     }
 #endif

PS: не проверял, но если сработает, запостите кто-нибудь в upstream.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от O02eg

У меня все в английской локали. И SDL2 как раз-таки хорошо уживается с Юникодом. Лучше по проблеме помогай, а не вбегай в тред с рандомными обвинениями :-)

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

кстати, вышла новая версия 2.0.3, может там пофиксили. сейчас ставлю

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

Немного offtopic

А вообще, в своё время, я забросил SDL в пользу чистого Xlib. С SDL слишком много проблем было. Зависит конечно от задачи, но для себя я выбор сделал.

PS: при этом я осознал, что Xlib на самом деле няшка и перестал понимать, почему его все боятся.

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

Попробуй вызвать X11_XCloseIM сразу после X11_XOpenIM.

O02eg ★★★★★
()
Ответ на: Немного offtopic от beastie

Xlib на самом деле няшка и перестал понимать, почему его все боятся.

Особенную ненависть Xlib и X11 вызывают, когда делаешь плагин. А уж если этот плагин должен корректно работать с нитями, а основное приложение забыло потокобезопасность инициализировать — вообще сказка. Почему, скажите мне, потокобезопасность вообще надо инициализировать?! Почему ошибки роняют программу? Почему обработка ошибок глобальная для всего приложения?

glxgears вызывает ошибку при закрытии. Багу лет немеряно, а авторы пишут, мол, не знаем, как починить. Это вообще как возможно?

Если Xlib и няшка, то только если ты не выходишь за некие невидимые границы.

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

мне кажется, нужно отслеживать состояние _this, потому что оттуда возвращается невалидный адрес (*data = _this->driverdata)

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

кстати, http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/02_getting...

Вот этот исходник из туториала (http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/02_getting...) компилится без ошибок. может, у меня где-то действительно проблемы с юникодом.. завтра гляну

mazdai ★★★
() автор топика
Последнее исправление: mazdai (всего исправлений: 1)
13 мая 2015 г.

Чуваки, вот решение. Функцию освобождения ресурсов (там, откуда вы вызываете SDL_Quit, у меня это shutdown() ), нужно объявить как static, потому что программа сегфолтится, когда вызывается эта функция. Если использовать atexit, такого не произойдет

теперь объясните, пожалуйста, откуда здесь вообще повторный вызов функции shutdown и почему он происходит из Xlib? Возможно, я неправильно понял вывод backtrace, но этого я понять не могу:


(gdb) up
#1  0x00007ffff6adee02 in XCloseIM () from /usr/lib/x86_64-linux-gnu/libX11.so.6
(gdb) back
#0  0x00007ffff6ba7895 in ?? () from /usr/lib/x86_64-linux-gnu/libX11.so.6
#1  0x00007ffff6adee02 in XCloseIM () from /usr/lib/x86_64-linux-gnu/libX11.so.6
#2  0x00007ffff7b93d3b in X11_VideoQuit (_this=<optimized out>) at /home/rustam/src/SDL2-2.0.2/src/video/x11/SDL_x11video.c:652
#3  0x00007ffff7b7bacb in SDL_VideoQuit_REAL () at /home/rustam/src/SDL2-2.0.2/src/video/SDL_video.c:2352
#4  0x00007ffff7ad6ac6 in SDL_QuitSubSystem_REAL (flags=<optimized out>) at /home/rustam/src/SDL2-2.0.2/src/SDL.c:297
#5  SDL_Quit_REAL () at /home/rustam/src/SDL2-2.0.2/src/SDL.c:357
#6  0x00000000004009c4 in shutdown () at main.c:45
#7  0x00007ffff6880786 in xcb_disconnect () from /usr/lib/x86_64-linux-gnu/libxcb.so.1
#8  0x00007ffff6ab04e7 in XCloseDisplay () from /usr/lib/x86_64-linux-gnu/libX11.so.6
#9  0x00007ffff7b93c9a in X11_DeleteDevice (device=0x607ad0) at /home/rustam/src/SDL2-2.0.2/src/video/x11/SDL_x11video.c:324
#10 0x00007ffff7b7bc2d in SDL_VideoQuit_REAL () at /home/rustam/src/SDL2-2.0.2/src/video/SDL_video.c:2377
#11 0x00007ffff7ad6ac6 in SDL_QuitSubSystem_REAL (flags=<optimized out>) at /home/rustam/src/SDL2-2.0.2/src/SDL.c:297
#12 SDL_Quit_REAL () at /home/rustam/src/SDL2-2.0.2/src/SDL.c:357
#13 0x00000000004009c4 in shutdown () at main.c:45
#14 0x00000000004009ed in main (argc=1, args=0x7fffffffe538) at main.c:55

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

А дело оказалось в том, что нефиг называть свои функции именами библиотечных:

NAME
       shutdown - shut down socket send and receive operations

SYNOPSIS
       #include <sys/socket.h>

       int shutdown(int socket, int how);

Вместо неё линкуется твоя (если объявлена без static), и xcb_disconnect радостно её вызывает :)

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

чувааак, спасибо, как я только о ней забыл ><

mazdai ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.