未定义对“WinMain@16”的引用

undefined reference to `WinMain@16'

提问人:Simplicity 提问时间:3/10/2011 最后编辑:John DiblingSimplicity 更新时间:6/20/2021 访问量:379396

问:

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

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

为什么?而且,我该如何解决这个问题?

C++ Eclipse-CDT

评论

3赞 yugsharma1711 3/21/2021
尝试保存您的文件并在我的情况下重新运行 它有效
0赞 Gertjan Brouwer 11/14/2023
就我而言,它是一个没有 int main() {} 函数的文件

答:

203赞 Cheers and hth. - Alf 3/10/2011 #1

当链接器找不到函数时,会发生此错误,因此可能缺少该函数。就你而言,你可能也失踪了。WinMainmain

请考虑以下 Windows API 级程序:

#define NOMINMAX
#include <windows.h>

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

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

C:\test> gnuc x.cpp

C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem               00000003        (Windows CUI)

C:\test> _

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

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

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

C:\test> gnuc x.cpp -mwindows

C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem               00000002        (Windows GUI)

C:\test> _

希望到目前为止没问题,尽管该标志只是半记录的。-mwindows

在没有该半文档标志的情况下进行构建时,必须更具体地告诉链接器需要哪个子系统值,并且通常必须显式指定某些 Windows API 导入库:

C:\test> gnuc x.cpp -Wl,-subsystem,windows

C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem               00000002        (Windows GUI)

C:\test> _

这在GNU工具链上工作得很好。

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

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

C:\test> msvc x.cpp user32.lib
x.cpp

C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
               3 subsystem (Windows CUI)

C:\test> _

但是,默认情况下,将 Microsoft 的工具链构建为 GUI 子系统不起作用:

C:\test> msvc x.cpp user32.lib /link /subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartu
p
x.exe : fatal error LNK1120: 1 unresolved externals

C:\test> _

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

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

您所要做的就是告诉 Microsoft 的链接器使用哪个入口点,即 ,哪个调用标准:mainCRTStartupmain

C:\test> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup
x.cpp

C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
               2 subsystem (Windows GUI)

C:\test> _

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

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

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

那么问题可能是什么呢?

好吧,您可能缺少一个.而且你可能也没有(适当的)!然后 g++,在搜索了(没有这样)和 Microsoft 的非标准(没有这样)之后,报告后者丢失了。mainWinMainmainWinMain

使用空源进行测试:

C:\test> type nul >y.cpp

C:\test> gnuc y.cpp -mwindows
c:/program files/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2): undefined referen
ce to `WinMain@16'
collect2: ld returned 1 exit status

C:\test> _

评论

3赞 Simplicity 3/10/2011
@Alf P. Steinbach。非常感谢您的好评。至于。有没有办法做到这一点,因为我没有使用命令行。谢谢All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard mainEclipse CDT
1赞 Cheers and hth. - Alf 3/10/2011
@user588855:由于您使用的是 G++,因此(可能)不适用于您。只有末尾的部分(可能)适用。也就是说,定义 或 ,或者确保相关文件包含在项目中。干杯mainWinMain
0赞 Simplicity 3/10/2011
@Alf P. Steinbach。定义或是什么意思?谢谢mainwinmain
0赞 Cheers and hth. - Alf 3/11/2011
@user588855:答案顶部的示例程序显示了一个标准函数。你需要在你的程序中(但有其他一些机构)。或者,您可以使用非标准 Microsoft ,但您需要拥有其中之一,并且该文件需要包含在项目中。mainWinMain
1赞 Indeed 12/30/2016
我刚刚制作了一个名为 main.cpp 的文件,其代码为:int main() { }
84赞 Tim Ludwinski 9/12/2012 #2

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

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

评论

0赞 Jeff Muir 3/23/2016
刚刚意识到这一切的一些重要事情。就我而言,它没有找到main(),因为我没有声明任何参数(argc,argv)。添加后,它找到了主要内容。此外,其工作方式的性质意味着 mingw 试图通过提供自己的 main 来提供帮助,而 main 又调用 WinMain。GUI 程序只有 WinMain,而 mingw 中的主存根用于到达那里。如果你有一个 main,那么它就会使用它。
0赞 driedler 10/2/2019
extern “C” int main(void) 为我解决了这个问题
0赞 Ted Lyngmo 11/4/2022
@driedler basic.start.main - “它的类型应该有C++语言链接,它应该有一个声明的 int 类型的返回类型,但除此之外,它的类型是实现定义的。” - 所以如果你必须给它 C 链接,似乎有些不对劲。
37赞 X-Frox 8/2/2014 #3

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

评论

0赞 8Observer8 5/3/2020
多谢!此命令有效: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
16赞 JabbaJava 7/19/2016 #4

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

-1赞 user7938860 11/15/2019 #5

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

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

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

(不确定此错误是否与最近更新的 IDE 有关 - 可能是因果关系,也可能只是相关关系。请随时对该因素发表任何见解!

4赞 mattylantz 9/8/2020 #6

我的情况是我没有主要功能。

0赞 Arturo Devesa 6/20/2021 #7

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