MinGW 上的 g++ 在使用 SDL2 时无法保留行号信息

g++ on MinGW can't keep line number information when using SDL2

本文关键字:保留 信息 SDL2 g++ 上的 MinGW      更新时间:2023-10-16

在MinGW而不是Unix中,当程序使用(甚至 #include 的(SDL2时,gdb没有行号信息。MCVE确实很简单:

#include "SDL.h" //<--comment this out and we get line numbers in gdb again
int main(int argc, char** argv)
{
return 0;
}

这是生成文件:

INCLUDE_FLAGS   :=  -I../../external/SDL2-MinGW/SDL2/i686-w64-mingw32/include/SDL2  
LIBRARIES       := mingw32 SDL2main SDL2                
LIB_FLAGS       := $(foreach library,$(LIBRARIES),    -l$(library))
LIB_DIR_FLAGS   := -L../../external/SDL2-MinGW/SDL2/i686-w64-mingw32/lib
ALL_FLAGS       := $(INCLUDE_FLAGS) $(LIB_FLAGS) $(LIB_DIR_FLAGS)
a.exe: main.cpp
g++ -Wall -g -o a.exe main.cpp $(ALL_FLAGS)  

这就是我如何称呼 gdb:

PATH="../../external/SDL2-MinGW/SDL2/i686-w64-mingw32/bin:$PATH"
gdb a.exe

我正在运行最新的MinGW(mingw-gcc-bin,mingw-gcc-g++-bin是9.2.0-1;mingw-gdb-bin是7.6.1-1(。

这里有什么解决方法?我不认为 SDL2 是用 -g 编译的,但这对 main 来说无关紧要。

编辑:输出显示在此处。

GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:Usersbriggs_wDesktopcpp-for-lazy-programmers-masterch29mcvea.exe...done.
(gdb) break main
Breakpoint 1 at 0x404270
(gdb) run
Starting program: C:Usersbriggs_wDesktopcpp-for-lazy-programmers-masterch29mcve/a.exe
[New Thread 8652.0x700]
[New Thread 8652.0xab8]
[New Thread 8652.0x36f0]
[New Thread 8652.0x244c]
Breakpoint 1, 0x00404270 in main ()
(gdb) next
Single stepping until exit from function main,
which has no line number information.
0x00401

SDL2 具有SDL2main库来处理不同目标平台上的入口点。 例如,在Unix系统上,您有main入口点,在Windows上 - 有时main,有时WinMain,而在例如Android或iOS上,情况可能非常不同。SDL 允许您假装入口点始终int main(int argc, char **argv),但它需要在此之前注入自己的实际入口点。为此,它使用#define main SDL_main,有效地将main重命名为SDL_main,然后在初始化阶段后调用它。因此,在您的情况下,中断调试器main无法显示行号,因为SDL2main在没有调试符号的情况下构建的;您的代码仍然具有符号,因此在代码中的任何位置中断将具有所有预期的内容。

作为旁注,因为您使用C++而不是 C:main绝对必须int main(int argc, char **argv).C++(或任何 C(允许 main 声明有更多的自由度,但是一旦它的名字不再main- 编译器不再知道它有任何特殊含义,并且会产生C++重整和通常的重载功能。这可能会导致意外的链接错误。

如果您自己实现入口点并通知 SDL 您不希望这样做,则可以删除SDL2main- 在包含SDL.h之前使用#define SDL_MAIN_HANDLED,并在任何其他 SDL 函数之前调用SDL_SetMainReady。在这种情况下,您不需要与SDL2main链接,但您将失去其额外的功能,例如utf8命令行参数。