【问题标题】:Basic SDL2 app compiles with MinGW-w64 but doesn't run基本 SDL2 应用程序使用 MinGW-w64 编译但不运行
【发布时间】:2020-08-04 18:51:48
【问题描述】:

我正在尝试使用 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,如 answered,它将在 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 DLL 文件放在可执行文件旁边。
  • 我从终端运行它,现在从资源管理器尝试它 - 它给了我Application Error: The application was unable to start correctly (0xc000007b). Click OK to close the application. 快速搜索显示它是 Windows 中相当通用的错误消息...
  • 而且,gdb 并没有真正让我到任何地方。无论我做什么,它都只是引用 crt0_c.c。 (gdb) run Starting program: **************\sdl_init_test.exe [New Thread 2332.0x3870] [New Thread 2332.0x4744] [New Thread 2332.0x24c8] [Thread 2332.0x24c8 exited with code 3221225595] [Thread 2332.0x3870 exited with code 3221225595] [Thread 2332.0x26ac exited with code 3221225595] During startup program exited with code 0xc000007b.

标签: c windows sdl-2 mingw-w64


【解决方案1】:

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

TL;DR 在 gdb 中使用 b SDL_main

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

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

【讨论】:

  • 感谢您的详尽解释!我不习惯 Windows 处理输出的方式,我真的从你的回答中学到了很多,无论是在 Windows 控制台上还是 SDL 在其中的工作方式。我基本上只是从在线教程中对那些 gcc windows 选项进行了 c/p,对它们的内部工作一无所知。而且,我盯着地板看-w,作为-Walljust-a-shortcut。呵呵。
  • 感谢您的回答,它帮助我通过这个问题的一个版本为自己找到了答案,但使用 cmake: do not set the WIN32 flag when using app_executable跨度>
猜你喜欢
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
相关资源
最近更新 更多