对“WinMain@16”的未定义引用
当我尝试使用 Eclipse CDT 构建程序时,我得到以下信息:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): 对“WinMain@16”的未定义引用
这是为什么?而且,我该如何解决这个问题?
When I try to build a program using Eclipse CDT
, I get the following:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106):
undefined reference to `WinMain@16
Why is that? And, how can I solve this issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
当链接器找不到
WinMain
函数时会发生此错误,因此它可能丢失。就您而言,您可能也缺少main
。考虑以下 Windows API 级程序:
现在让我们使用 GNU 工具链(即 g++)构建它,没有特殊选项。这里的 gnuc 只是我用于此目的的一个批处理文件。它仅提供使 g++ 更加标准的选项:
这意味着链接器默认生成一个控制台子系统可执行文件。文件头中的子系统值告诉Windows该程序需要哪些服务。在这种情况下,使用控制台系统,该程序需要一个控制台窗口。
这也会导致命令解释器等待程序完成。
现在让我们用GUI子系统来构建它,这仅仅意味着该程序不需要控制台窗口:
希望到目前为止没问题,尽管
-mwindows
标志只是半-记录在案。如果没有半文档标志,则必须更具体地告诉链接器需要哪个子系统值,然后通常必须明确指定一些 Windows API 导入库:
使用 GNU 工具链,效果很好。
但是 Microsoft 工具链(即 Visual C++)又如何呢?
好吧,构建为控制台子系统可执行文件工作正常:
但是,使用 Microsoft 的工具链构建为 GUI 子系统默认情况下不起作用:
从技术上讲,这是因为 Microsoft 的链接器默认情况下对于 GUI 子系统来说是非标准的。默认情况下,当子系统是 GUI 时,Microsoft 的链接器使用运行时库入口点,即机器代码执行开始的函数,称为
winMainCRTStartup
,它调用 Microsoft 的非标准WinMain
而不是标准main
。不过,解决这个问题没什么大不了的。
您所要做的就是告诉微软的链接器使用哪个入口点,即
mainCRTStartup
,它调用标准main
:没问题,但非常乏味。而且如此神秘和隐蔽,以至于大多数 Windows 程序员(大多只使用 Microsoft 的非标准默认工具)甚至不知道它,并错误地认为 Windows GUI 子系统程序“必须”具有非标准
WinMain
而不是标准的main
。顺便说一句,对于 C++0x,微软将遇到一个问题,因为编译器必须通告它是独立的还是托管的(托管时它必须支持标准main
)。无论如何,这就是 g++ 抱怨
WinMain
缺失的原因:这是一个愚蠢的非标准启动函数,Microsoft 的工具默认需要 GUI 子系统程序。但正如您在上面所看到的,即使对于 GUI 子系统程序,g++ 对于标准
main
也没有问题。那么可能是什么问题呢?
好吧,您可能缺少一个
main
。而且您可能也没有(正确的)WinMain
!然后,g++ 在搜索了main
(没有这样的)和 Microsoft 的非标准WinMain
(没有这样的)之后,报告后者丢失了。使用空源进行测试:
This error occurs when the linker can't find
WinMain
function, so it is probably missing. In your case, you are probably missingmain
too.Consider the following Windows API-level program:
Now let's build it using GNU toolchain (i.e. g++), no special options. Here
gnuc
is just a batch file that I use for that. It only supplies options to make g++ more standard:This means that the linker by default produced a console subsystem executable. The subsystem value in the file header tells Windows what services the program requires. In this case, with console system, that the program requires a console window.
This also causes the command interpreter to wait for the program to complete.
Now let's build it with GUI subsystem, which just means that the program does not require a console window:
Hopefully that's OK so far, although the
-mwindows
flag is just semi-documented.Building without that semi-documented flag one would have to more specifically tell the linker which subsystem value one desires, and some Windows API import libraries will then in general have to be specified explicitly:
That worked fine, with the GNU toolchain.
But what about the Microsoft toolchain, i.e. Visual C++?
Well, building as a console subsystem executable works fine:
However, with Microsoft's toolchain building as GUI subsystem does not work by default:
Technically this is because Microsoft’s linker is non-standard by default for GUI subsystem. By default, when the subsystem is GUI, then Microsoft's linker uses a runtime library entry point, the function where the machine code execution starts, called
winMainCRTStartup
, that calls Microsoft's non-standardWinMain
instead of standardmain
.No big deal to fix that, though.
All you have to do is to tell Microsoft's linker which entry point to use, namely
mainCRTStartup
, which calls standardmain
:No problem, but very tedious. And so arcane and hidden that most Windows programmers, who mostly only use Microsoft’s non-standard-by-default tools, do not even know about it, and mistakenly think that a Windows GUI subsystem program “must” have non-standard
WinMain
instead of standardmain
. In passing, with C++0x Microsoft will have a problem with this, since the compiler must then advertize whether it's free-standing or hosted (when hosted it must support standardmain
).Anyway, that's the reason why g++ can complain about
WinMain
missing: it's a silly non-standard startup function that Microsoft's tools require by default for GUI subsystem programs.But as you can see above, g++ has no problem with standard
main
even for a GUI subsystem program.So what could be the problem?
Well, you are probably missing a
main
. And you probably have no (proper)WinMain
either! And then g++, after having searched formain
(no such), and for Microsoft's non-standardWinMain
(no such), reports that the latter is missing.Testing with an empty source:
总结一下 Cheers 和 hth 的上述帖子。 - Alf,确保定义了
main()
或WinMain()
并且 g++ 应该做正确的事情。我的问题是
main()
被意外定义在命名空间内。To summarize the above post by Cheers and hth. - Alf, Make sure you have
main()
orWinMain()
defined and g++ should do the right thing.My problem was that
main()
was defined inside of a namespace by accident.我在使用 SDL 编译应用程序时遇到此错误。这是由于 SDL 在 SDL_main.h 中定义了自己的 main 函数所致。为了防止 SDL 定义 main 函数,必须在包含 SDL.h 标头之前定义 SDL_MAIN_HANDLED 宏。
I was encountering this error while compiling my application with SDL. This was caused by SDL defining it's own main function in SDL_main.h. To prevent SDL define the main function an SDL_MAIN_HANDLED macro has to be defined before the SDL.h header is included.
尝试在构建之前保存 .c 文件。我相信您的计算机正在引用一个文件的路径,其中没有任何信息。
Try saving your .c file before building. I believe your computer is referencing a path to a file with no information inside of it.
我的情况是我没有主要功能。
My situation was that I did not have a main function.
您缺少
main()
函数(或WinMain()
)。如果您确实有,您可能忘记保存源代码代码,最终编译出一个空文件(没有
main()
)。您可以使用
main
或WinMain
。错误总是会显示WinMain
,这是一条鲱鱼,您始终可以在 MinGW 上使用其中之一。在 MinGW 上,
main
与WinMain
的选择与其他答案讨论的“子系统”设置(“windows”与“console”)无关。子系统仅在 MSVC 编译器上对此起作用。如果您使用的是 SDL2:
那么上述内容不适用于您,因为 SDL2 提供了自己的
main
函数。它将您的重命名为SDL_main
(通过#define main SDL_main
)并从他们的中调用它。那么该错误意味着您忘记了
-lSDL2main
链接器标志。如果您确实有,请确保标志顺序正确:
.c
/.cpp
/.o
文件,然后-lmingw32 -lSDL2main -lSDL2
。如果仍然不起作用,则您使用的 SDL2 版本可能与您的编译器不兼容。如果您使用的是 MSYS2,请考虑安装他们的 SDL2 版本(保证兼容)。否则,您可能会使用带有 x64 编译器的 x32 SDL2,反之亦然。您下载的 SDL2 文件位于两个目录:
i686...
(x32) 和x86_64
(x64),请同时尝试。如果您正确执行了所有操作,则无需定义
SDL_MAIN_HANDLED
。You're missing the
main()
function (orWinMain()
).If you do have one, you probably forgot to save your source code, and ended up compiling an empty file (without
main()
).You can use either
main
orWinMain
. The error will always sayWinMain
, which is a hed herring, you can always use either one on MinGW.On MinGW, the choice of
main
vsWinMain
is unrelated to the "subsystem" setting ("windows" vs "console") that other answer talks about. The subsystem only matters for this on the MSVC compiler.If you're using SDL2:
Then the above doesn't apply to you, because SDL2 provides its own
main
function. It renames yours toSDL_main
(via#define main SDL_main
) and calls it from theirs.Then the error means that you forgot the
-lSDL2main
linker flag.If you do have, it, make sure that the flag order is correct:
.c
/.cpp
/.o
files, then-lmingw32 -lSDL2main -lSDL2
.If that still doesn't work, the version of SDL2 you're using is likely incompatible with your compiler. If you're using MSYS2, consider installing their version of SDL2 (which is guaranteed to be compatible). Otherwise, you're likely using x32 SDL2 with x64 compiler, or vice versa. The SDL2 files you've downloaded come in two directries:
i686...
(x32) andx86_64
(x64), try both.Defining
SDL_MAIN_HANDLED
is never necessary if you do everything correctly.检查您的项目中是否包含所有文件:
更新 cLion 后,我也弹出了同样的错误。经过几个小时的修补后,我注意到我的一个文件没有包含在项目目标中。将其添加回活动项目后,我停止获取对 winmain16 的未定义引用,并且代码已编译。
编辑:检查 IDE 中的构建设置也是值得的。
(不确定此错误是否与最近更新 IDE 相关 - 可能是因果关系,也可能只是相关性。请随意发表评论,提供有关该因素的任何见解!)
Check that All Files are Included in Your Project:
I had this same error pop up after I updated cLion. After hours of tinkering, I noticed one of my files was not included in the project target. After I added it back to the active project, I stopped getting the undefined reference to winmain16, and the code compiled.
Edit: It's also worthwhile to check the build settings within your IDE.
(Not sure if this error is related to having recently updated the IDE - could be causal or simply correlative. Feel free to comment with any insight on that factor!)
有同样的问题。为了解决这个问题,我在构建之前单击“保存”来保存我的 .c 文件。我相信我的计算机正在引用一个文件的路径,其中没有任何信息。
Had same problem. To fix it I clicked save to save my .c file before building. I believe my computer was referencing a path to a file with no information inside of it.