对“WinMain@16"的未定义引用 [英] undefined reference to `WinMain@16'

查看:43
本文介绍了对“WinMain@16"的未定义引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

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

的未定义引用

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

解决方案

当链接器找不到 WinMain 函数时会出现此错误,因此它可能丢失了.就您而言,您可能也缺少 main.

考虑以下 Windows API 级程序:

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

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

<前>C:测试>gnux.cppC:测试>objdump -x a.exe |findstr/i "^子系统"子系统 00000003 (Windows CUI)C:测试>_

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

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

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

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

希望到目前为止一切正常,尽管 -mwindows 标志只是半文档化.

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

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

使用 GNU 工具链效果很好.

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

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

<前>C:测试>msvc x.cpp user32.libx.cppC:测试>dumpbin/headers x.exe |找到/i "子系统" |找到/i "Windows"3 子系统(Windows CUI)C:测试>_

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

<前>C:测试>msvc x.cpp user32.lib/link/subsystem:windowsx.cppLIBCMT.lib(wincrt0.obj):错误 LNK2019:未解析的外部符号 _WinMain@16 在函数 ___tmainCRTStartu 中引用px.exe:致命错误 LNK1120:1 未解析的外部C:测试>_

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

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

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

<前>C:测试>msvc x.cpp user32.lib/link/subsystem:windows/entry:mainCRTStartupx.cppC:测试>dumpbin/headers x.exe |找到/i "子系统" |找到/i "Windows"2 子系统(Windows GUI)C:测试>_

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

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

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

那可能是什么问题?

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

使用空源进行测试:

<前>C:测试>输入 nul >y.cppC:测试>gnuc y.cpp -mwindowsc:/program files/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2): 未定义的引用ce 到`WinMain@16'collect2: ld 返回 1 个退出状态C:测试>_

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?

解决方案

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:	est> gnuc x.cpp

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

C:	est> _

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:	est> gnuc x.cpp -mwindows

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

C:	est> _

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:	est> gnuc x.cpp -Wl,-subsystem,windows

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

C:	est> _

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:	est> msvc x.cpp user32.lib
x.cpp

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

C:	est> _

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

C:	est> 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:	est> _

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:	est> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup
x.cpp

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

C:	est> _

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:	est> type nul >y.cpp

C:	est> 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:	est> _

这篇关于对“WinMain@16"的未定义引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆