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

发布于 2024-10-21 05:50:13 字数 182 浏览 2 评论 0原文

当我尝试使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

醉城メ夜风 2024-10-28 05:50:13

当链接器找不到 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 "^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 的链接器使用运行时库入口点,即机器代码执行开始的函数,称为 winMainCRTStartup,它调用 Microsoft 的非标准 WinMain 而不是标准 main

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

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

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 子系统程序“必须”具有非标准 WinMain 而不是标准的 main。顺便说一句,对于 C++0x,微软将遇到一个问题,因为编译器必须通告它是独立的还是托管的(托管时它必须支持标准 main)。

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

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

那么可能是什么问题呢?

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

使用空源进行测试:

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> _

This error occurs when the linker can't find WinMain function, so it is probably missing. In your case, you are probably missing main too.

Consider the following Windows API-level program:

#define NOMINMAX
#include <windows.h>

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

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:

C:\test> gnuc x.cpp

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

C:\test> _

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:

C:\test> gnuc x.cpp -mwindows

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

C:\test> _

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:

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

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

C:\test> _

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:

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> _

However, with Microsoft's toolchain building as GUI subsystem does not work by default:

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> _

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-standard WinMain instead of standard main.

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 standard main:

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> _

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 standard main. 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 standard main).

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 for main (no such), and for Microsoft's non-standard WinMain (no such), reports that the latter is missing.

Testing with an empty source:

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> _
铃予 2024-10-28 05:50:13

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

我的问题是 main() 被意外定义在命名空间内。

To summarize the above post by Cheers and hth. - Alf, Make sure you have main() or WinMain() defined and g++ should do the right thing.

My problem was that main() was defined inside of a namespace by accident.

倚栏听风 2024-10-28 05:50:13

我在使用 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.

誰認得朕 2024-10-28 05:50:13

尝试在构建之前保存 .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.

海风掠过北极光 2024-10-28 05:50:13

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

My situation was that I did not have a main function.

吃素的狼 2024-10-28 05:50:13

您缺少 main() 函数(或 WinMain())。

如果您确实有,您可能忘记保存源代码代码,最终编译出一个空文件(没有 main())。

您可以使用 mainWinMain。错误总是会显示 WinMain,这是一条鲱鱼,您始终可以在 MinGW 上使用其中之一。

在 MinGW 上, mainWinMain 的选择与其他答案讨论的“子系统”设置(“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 (or WinMain()).

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 or WinMain. The error will always say WinMain, which is a hed herring, you can always use either one on MinGW.

On MinGW, the choice of main vs WinMain 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 to SDL_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) and x86_64 (x64), try both.

Defining SDL_MAIN_HANDLED is never necessary if you do everything correctly.

一腔孤↑勇 2024-10-28 05:50:13

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

更新 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!)

梦言归人 2024-10-28 05:50:13

有同样的问题。为了解决这个问题,我在构建之前单击“保存”来保存我的 .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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文