【问题标题】:undefined reference to `WinMain@16'未定义对“WinMain@16”的引用
【发布时间】:2021-11-18 23:54:20
【问题描述】:

当我尝试使用Eclipse CDT 构建程序时,我得到以下信息:

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): 未定义对 `WinMain@16

的引用

这是为什么呢?还有,我该如何解决这个问题?

【问题讨论】:

  • 尝试保存您的文件并在我的情况下重新运行它成功了

标签: c++ eclipse eclipse-cdt


【解决方案1】:

当链接器找不到WinMain 函数时会发生此错误,因此它可能丢失了。在您的情况下,您可能也缺少main

考虑以下 Windows API 级程序:

#define NOMINMAX
#include <windows.h>

int main()
{
    MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}

现在让我们使用 GNU 工具链(即 g++)构建它,没有特殊选项。这里gnuc 只是我使用的一个批处理文件。它只提供使 g++ 更标准的选项:

C:\test> gnuc x.cpp C:\test> objdump -x a.exe | findstr /i "^子系统" 子系统 00000003 (Windows CUI) C:\测试> _

这意味着链接器默认生成一个控制台子系统可执行文件。文件头中的 subsystem 值告诉 Windows 程序需要哪些服务。在这种情况下,使用控制台系统,该程序需要一个控制台窗口。

这也会导致命令解释器等待程序完成。

现在让我们用GUI子系统构建它,这只是意味着程序不需要控制台窗口:

C:\test> gnuc x.cpp -mwindows C:\test> objdump -x a.exe | findstr /i "^子系统" 子系统 00000002 (Windows GUI) C:\测试> _

希望到目前为止一切正常,尽管 -mwindows 标志只是半记录的。

在没有半文档化标志的情况下构建时,必须更具体地告诉链接器需要哪个子系统值,然后通常必须明确指定一些 Windows API 导入库:

C:\test> gnuc x.cpp -Wl,-subsystem,windows C:\test> objdump -x a.exe | findstr /i "^子系统" 子系统 00000002 (Windows GUI) C:\测试> _

使用 GNU 工具链效果很好。

但是 Microsoft 工具链(即 Visual C++)呢?

好吧,构建为控制台子系统可执行文件可以正常工作:

C:\test> msvc x.cpp user32.lib x.cpp C:\test> dumpbin /headers x.exe |查找 /i "子系统" |查找 /i "Windows" 3 子系统 (Windows CUI) C:\测试> _

然而,微软将工具链构建为 GUI 子系统默认情况下不起作用:

C:\test> msvc x.cpp user32.lib /link /subsystem:windows x.cpp LIBCMT.lib(wincrt0.obj):错误 LNK2019:未解析的外部符号 _WinMain@16 在函数 ___tmainCRTStartu 中引用 p x.exe : 致命错误 LNK1120: 1 unresolved externals C:\测试> _

从技术上讲,这是因为微软的链接器默认情况下对于 GUI 子系统是非标准的。默认情况下,当子系统为GUI时,微软的链接器使用运行时库入口点,机器代码执行开始的函数,称为winMainCRTStartup,它调用微软的非标准@ 987654327@ 而不是标准的main

不过,解决这个问题没什么大不了的。

你所要做的就是告诉微软的链接器使用哪个入口点,即mainCRTStartup,它调用标准的main

C:\test> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup x.cpp C:\test> dumpbin /headers x.exe |查找 /i "子系统" |查找 /i "Windows" 2 子系统(Windows GUI) C:\测试> _

没问题,但是很乏味。如此神秘和隐藏,以至于大多数只使用微软默认的非标准工具的大多数 Windows 程序员甚至都不知道它,并错误地认为 Windows GUI 子系统程序“必须”具有非标准 WinMain而不是标准的main。顺便说一句,对于 C++0x,Microsoft 会遇到这个问题,因为编译器必须宣传它是独立的还是托管的(托管时它必须支持标准 main)。

无论如何,这就是为什么 g++可以抱怨WinMain 缺失的原因:这是一个愚蠢的非标准启动功能,微软的工具默认需要 GUI 子系统程序。

但正如您在上面看到的,g++ 对标准main 没有问题,即使对于 GUI 子系统程序也是如此。

那么可能是什么问题?

好吧,您可能缺少main。而且您可能也没有(正确的)WinMain!然后 g++ 在搜索了main(没有这个)和微软的非标准WinMain(没有这个)之后,报告说后者丢失了。

使用空源进行测试:

C:\test> 键入 nul >y.cpp C:\test> gnuc y.cpp -mwindows c:/程序文件/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2 ): 未定义的引用 ce 到 `WinMain@16' collect2: ld 返回 1 个退出状态 C:\测试> _

【讨论】:

  • @Alf P. Steinbach。非常感谢你的好回复。至于All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main。有没有办法做到这一点Eclipse CDT,因为我没有使用命令行。谢谢
  • @user588855:因为您使用的是 g++,所以(可能)不适用于您。只有最后的部分(可能)适用。也就是说,定义mainWinMain,或者,确保相关文件包含在项目中。干杯,
  • @Alf P. Steinbach。定义mainwinmain 是什么意思?谢谢
  • 我刚刚创建了一个名为 main.cpp 的文件,其代码为:int main() { }
  • 如果每个投反对票的人都能解释投反对票,我会很好。因为可能其他读者有同样的误解(不管它是什么),然后我们可以澄清它。每个人都会受益,而不是一些人被误导。所以,请解释你的反对意见。谢谢。
【解决方案2】:

总结一下 Cheers and hth 的上述帖子。 - Alf,确保你定义了 main()WinMain() 并且 g++ 应该做正确的事情。

我的问题是 main() 是偶然在命名空间内定义的。

【讨论】:

  • 刚刚意识到这一切很重要。就我而言,它没有找到 main(),因为我没有声明任何参数(argc,argv)。添加后,它找到了main。此外,其工作方式的本质意味着 mingw 试图通过提供自己的 main 来提供帮助,而 main 又调用 WinMain。 GUI 程序只有 WinMain,而 mingw 中的主存根用于到达那里。如果你有一个 main,那么它会使用它。
  • extern "C" int main(void) 为我解决了这个问题
【解决方案3】:

我在使用 SDL 编译我的应用程序时遇到了这个错误。这是由 SDL 在 SDL_main.h 中定义它自己的 main 函数引起的。为了防止 SDL 定义 main 函数,必须在包含 SDL.h 标头之前定义 SDL_MAIN_HANDLED 宏。

【讨论】:

  • 非常感谢!此命令有效: gcc main.c -I"E:\Libs\SDL2-devel-2.0.12-mingw\SDL2-2.0.12\i686-w64-mingw32\include" -I"E:\Libs\SDL2_ttf- devel-2.0.15-mingw\SDL2_ttf-2.0.15\i686-w64-mingw32\include"-L"E:\Libs\SDL2-devel-2.0.12-mingw\SDL2-2.0.12\i686-w64- mingw32\lib" -L"E:\Libs\SDL2_ttf-devel-2.0.15-mingw\SDL2_ttf-2.0.15\i686-w64-mingw32\lib" -lSDL2 -lSDL2main -lSDL2_ttf -o app.exe
【解决方案4】:

尝试在构建之前保存您的 .c 文件。我相信您的计算机正在引用一个文件的路径,其中没有任何信息。

【讨论】:

    【解决方案5】:

    检查您的项目中是否包含所有文件:

    我在更新 cLion 后弹出了同样的错误。经过数小时的修补,我注意到我的一个文件未包含在项目目标中。将其添加回活动项目后,我停止获取对 winmain16 的未定义引用,并且代码已编译。

    编辑:检查 IDE 中的构建设置也是值得的。

    (不确定此错误是否与最近更新了 IDE 有关 - 可能是因果关系或只是相关的。请随时评论有关该因素的任何见解!)

    【讨论】:

      【解决方案6】:

      我的情况是我没有main函数。

      【讨论】:

        【解决方案7】:

        有同样的问题。为了修复它,我在构建之前单击了保存以保存我的 .c 文件。我相信我的计算机引用了一个文件的路径,其中没有任何信息。

        【讨论】:

          猜你喜欢
          • 2013-01-15
          相关资源
          最近更新 更多