SDL2& GDB:程序收到信号?,未知信号

时间:2017-05-08 19:53:57

标签: c++ gcc gdb sdl-2

让我们先来描述一下发生了什么:

我在Windows上玩SDL2库。我可以使用它编译程序,当我运行.exe时它工作得很好。当我尝试使用GDB调试它时出现问题 - 当代码进入SDL_Init或SDL_OpenAudio函数(可能创建新线程),GDB停止,显示“程序接收信号?,未知信号”消息,并且当我恢复执行时程序崩溃。

显然GDB(https://www.mail-archive.com/cygwin@cygwin.com/msg149735.html)中存在与线程命名相关的错误,应该在GDB版本7.11.1-1中修复。

起初我使用GCC 5.1.0(TDM)和GDB 7.6.1,所以我决定更新到更新的版本。看起来大约两年前TDM没有提供任何更新,所以我安装了MinGW-w64(我现在不记得了,但它可能是GDB的7.11版本)。没有帮助,GDB stil崩溃。

接下来我搜索了更新版本的GDB,找到了7.12(www dot equation dot com / servlet / equation.cmd?fa = gdb)。也没用,也许修复没有达到这个版本。

显然这个bug应该只出现在x86版本的GDB中,所以我安装了x64版本的TDM(GCC 5.1.0和GDB 7.9.1)。程序编译正常,但GDB仍然捕获未知信号和程序崩溃。

现在我实际上无法使用SDL2调试任何程序。所以,问题是,我能做些什么让它再次运作?

可能的解决方案:

  • 使用Visual Studio - 我喜欢Eclipse(这意味着我开始容忍我不喜欢的东西)并且不想学习全新的IDE,但我会将其作为最后一个选项。< / LI>
  • 编译GDB - 尝试过,没有用,在Windows上编译的东西几乎从不适用于我,GDB 7.12也有这个bug。
  • 切换到Linux - 比转移到Visual Studio更加激进。
  • 回归到SDL 1.2 - 那时事情变得更加轻松......
  • 切换到任何其他库 - ...并希望他们能与GDB合作。这听起来并不像解决方案。
  • 切换到不同的编译器?
  • 禁用线程命名?

代码示例:

#include <SDL2/SDL.h>

// Normally I'd use #undef main
int WinMain(int, char**)
    {
    SDL_Init(SDL_INIT_EVERYTHING);

    return 0;
    }

编译:g ++ gdbtest.cpp -lSDL2main -lSDL2

SDL2版本:2.0.5(适用于Windows的最新版本,MinGW,32位版本)

正常运行:a.exe

结果:程序正常开始和结束

使用GDB运行:Console log

结果:GDB收到未知信号,程序崩溃

2 个答案:

答案 0 :(得分:4)

好的,我想我找到了两种解决方法。问题的根源在于GDB如何处理(或至少应该处理)线程命名。要命名一个线程,必须使用特定属性引发异常。 SDL2在位于SDL2-2.0.5 / src / thread / windows / SDL_systhread.c中的SDL_SYS_SetupThread函数中执行此操作:168:

RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);

第一个选项是注释这一行并重新编译库(好吧,编译它本身就是一个问题)。 第二个选项是添加:

SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
在代码早期的某个地方 - 在SDL_SYS_SetupThread函数中,调用SDL_GetHintBoolean,如果SDL_HINT_WINDOWS _...为false,则从函数返回而不命名任何内容。

尽管如此,找到解决这个错误的方法并不意味着它不会再回来困扰我从一些其他库中命名它的线程。

答案 1 :(得分:3)

根据您的新信息,我可以成功地重现您的问题并设法缩小其原因(但不是根本原因或问题)。但首先,考虑一下如何编译和链接您的程序:

  • #include <SDL2/SDL.h>:我将其更改为#include "SDL.h",并使用-I调整包含路径以指向SDL的include文件夹。这样您的代码就更具可移植性,因为sdl2-config命令输出应传递给编译器的标志,而-I就是其中之一。
  • // Normally I'd use #undef main:不要这样做,不需要。你应该做的是调整链接和编译选项。 SDL2的“主要技巧”必须按预期工作。
  • g++ gdbtest.cpp -lSDL2main -lSDL2:正如this wiki entry所指出的那样,Windows的正确链接标记通常是-lmingw32 -lSDL2main -lSDL2 -mwindows
  • return 0:请不要忘记在申请结束时致电SDL_Quit()

现在,您遇到的问题是传递给SDL_Init的某些标志导致gdb失败(过去,我记得其中一些导致挂断,但不是案件了。所以,为了直接解决你的问题,我没有通过SDL_INIT_EVERYTHING,而是通过了

SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_HAPTIC | SDL_INIT_HAPTIC | SDL_INIT_EVENTS

遗漏以下内容:

SDL_INIT_TIMER | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER

gdb a.exe正常运行。

正如我之前所说,我没有进一步检查为什么它会导致GDB失败,但这肯定是一个值得报道的错误。我会去https://bugzilla.libsdl.org/,搜索一个类似于它的bug,如果找不到就会创建。