基本 SDL2 应用程序可以使用 MinGW-w64 编译,但不能 运行

Basic SDL2 app compiles with MinGW-w64 but doesn't run

我正在尝试使用 MinGW-w64 在 Windows 10 上设置 SDL2 和 C 开发环境。

当尝试 运行 具有 SDL 初始化的基本 c 应用程序时,它编译时没有警告,但之后 运行 失败,再次没有任何警告。可执行文件刚刚退出。

来源如下:

#include<SDL2/SDL.h>

int main(int argc, char* argv[]) {

    puts("\nmain...\n");

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("\nInit error: %s\n", SDL_GetError());
    }
    else {
        puts("\nSDL init success...");
    }
}

... 和生成文件:

OBJS = sdl_init.c
EXE_NAME = sdl_init_test
CFLAGS_W = -w -Wl,-subsystem,windows
LFLAGS_W = -lmingw32 -lSDL2main -lSDL2
INCS_W = -IC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\include
LIBS_W = -LC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\lib

windows_debug:
    gcc $(OBJS) $(INCS_W) $(LIBS_W) $(CFLAGS_W) $(LFLAGS_W) -g -o $(EXE_NAME).exe

...以及 gdb 的奇怪输出:

Reading symbols from .\sdl_init_test.exe...
(gdb) list main
12      ../../src/mingw-w64-crt/crt/crt0_c.c: No such file or directory.
(gdb) b main
Breakpoint 1 at 0x402e70: file ../../src/mingw-w64-crt/crt/crt0_c.c, line 17.

我假设我在链接阶段做错了什么,但无法准确指出。 在 Linux 上,一切都按预期编译、运行 和调试。


这是一个更正的 makefile,如 将在 Windows 控制台中正常编译和工作:

SRC = sdl_init.c
EXE_NAME = sdl_init_test

CFLAGS_W = -Wall -Wl,-subsystem,console
LFLAGS_W = -lmingw32 -lSDL2main -lSDL2
INCS_W = -IC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\include
LIBS_W = -LC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\lib


windows_debug:
    gcc $(SRC) $(INCS_W) $(LIBS_W) $(CFLAGS_W) $(LFLAGS_W) -g -o $(EXE_NAME).exe

除了缺少动态库的启动问题外,您似乎被误导了(可以说是 SDL 实际上在这方面具有误导性)您在 gdb 中的 b main 您的 [= 中设置了断点40=] main 函数。这不是 SDL redefines mainSDL_main 的情况,所以如果你有 #include "SDL2.h" 或类似的东西并且 SDL 为你的操作系统实现了主要包装 - 你的函数被重命名.在内部 main(或 wmain,或 WinMain,或任何目标系统用作 user-defined 代码入口点)在 SDL2main 库中实现,您 link 并调用 SDL_main(您的代码)。

TL;DR 在 gdb 中使用 b SDL_main

第二点是您看不到输出文本的原因。这又是 windows 特定的,主要是因为您构建了“GUI”应用程序,它不同于“控制台”应用程序,并且其 stdout 并没有真正与控制台输出相关联。输出仍然存在,但您看不到它 - 但它可以重定向到其他程序或文件,例如your_program.exe | moreyour_program.exe > stdout.txt。有一些方法可以将 stdout 重新连接到控制台(我记得有些 freopen 具有 CON 魔法),或者您可以只构建控制台程序而不是 -Wl,-subsystem,console.

作为旁注,-w 编译器标志(可以粗略地理解为“永远不要警告我我的代码有任何潜在问题,因为我 100% 确定它绝对完美并且你所有的警告都是对我完美代码的无理抱怨”(抱歉))是一个非常非常糟糕的主意,除了一些非常罕见的例外。编译器,尤其是 gcc 和 clang,非常擅长在真正重要的地方发出警告,让您及早发现错误。您想要更多警告(例如 -Wall -Wextra,可能更多),而不是根本没有警告。当我们讨论它时,makefile 中的 OBJS 在逻辑上应该表示目标文件,而不是源文件(当然,从技术上讲,您可以随意调用您的变量,这只是误导)。