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

SDL2 & GDB: program received signal ?, unknown signal

让我们从描述发生的事情开始:

我正在 Windows 上玩 SDL2 库。我可以使用它编译程序,当我 运行 .exe 时它工作得很好。当我尝试使用 GDB 调试它时出现问题 - 当代码到达 SDL_Init 或 SDL_OpenAudio 函数(可能创建新线程)时,GDB 停止,显示 "program received signal ?, unknown signal" 消息,并且当我恢复执行程序崩溃了。

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 仍然崩溃。

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

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

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


可能的解决方案:


代码示例:

#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 接收到未知信号,程序崩溃

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

  • #include <SDL2/SDL.h>:我会将其更改为 #include "SDL.h" 并使用 -I 调整您的包含路径以指向 SDL 的包含文件夹。这样你的代码更可移植,因为 sdl2-config 命令输出应该传递给编译器的标志,-I 就是其中之一。
  • // Normally I'd use #undef main:不要这样做,不需要。您应该做的是调整 link 和编译选项。 SDL2 的“主要技巧”必须按预期工作。
  • g++ gdbtest.cpp -lSDL2main -lSDL2:Windows 的正确 linking 标志通常是 this wiki entry 所指出的:-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/,搜索与之类似的错误,如果找不到就创建。

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

的 SDL_SYS_SetupThread 函数中执行此操作
RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);

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

SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");

代码早期的某个地方 - 在 SDL_SYS_SetupThread 函数中,如果 SDL_HINT_WINDOWS_... 为假,则从函数 returns 调用 returns 而不命名任何内容。

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