提问者:小点点

未定义对`WinMain@16'的引用


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

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

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


共3个答案

匿名用户

请考虑以下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> _

但是,用微软的工具链构建作为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> _

从技术上讲,这是因为微软的链接器对于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程序员--他们大多只使用微软的非标准默认工具--甚至对此一无所知,误以为一个Windows GUI子系统程序“必须”有非标准的WinMain而不是标准的Main。 顺便说一下,对于C++0x,Microsoft在这方面会有一个问题,因为编译器必须通告它是独立的还是托管的(托管时,它必须支持标准的main)。

不管怎么说,这就是G++可以抱怨Winmain缺失的原因:它是微软的工具默认为GUI子系统程序所需要的一个愚蠢的非标准启动函数。

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

那么问题出在哪里呢?

那么,您可能缺少一个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> _

匿名用户

用Cheers和hth来总结上面的帖子。 -Alf,确保您定义了main()Winmain(),并且g++应该做正确的事情。

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

匿名用户

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