【问题标题】:SDL2 & GDB: program received signal ?, unknown signalSDL2 & GDB:节目接收信号?,未知信号
【发布时间】:2017-10-06 23:08:13
【问题描述】:

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

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

接下来我搜索了更新版本的 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 调试任何程序。所以,问题是,我该怎么做才能让它再次工作?


可能的解决方案:

  • 使用 Visual Studio - 我喜欢 Eclipse(这意味着我开始容忍我不喜欢的东西)并且不想学习全新的 IDE,但我会保留它作为最后的选择。
  • 编译 GDB - 试过了,但没用,在 Windows 上编译东西几乎不适合我,而且 GDB 7.12 也有这个错误。
  • 切换到 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 收到未知信号,程序崩溃

【问题讨论】:

  • 没什么可做的。你能发布一些最小的代码来帮助我们理解吗?发布有关您的环境的更多信息 - 您使用的确切库、用于编译和链接的命令行参数等...
  • 完成 - 代码尽可能少。

标签: c++ gcc gdb sdl-2


【解决方案1】:

好的,我想我找到了两种处理方法。问题的根源在于 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_... 为 false,则调用 SDL_GetHintBoolean 从函数返回而不命名任何内容。

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

【讨论】:

    【解决方案2】:

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

    • #include &lt;SDL2/SDL.h&gt;:我将其更改为 #include "SDL.h" 并使用 -I 调整包含路径以指向 SDL 的包含文件夹。这样,您的代码更易于移植,因为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/,搜索一个类似的错误,如果没有找到就创建。

    【讨论】:

    • 保留这些标志确实可以修复我的示例程序,但是当我添加 SDL_OpenAudio 或 MIX_OpenAudio 时它会崩溃。每次创建和命名线程时似乎都会发生这种情况(我猜 SDL_INIT_TIMER 启动一个)。我尝试过的每个 GDB 版本似乎都不支持。
    猜你喜欢
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多