未定义引用'WinMain @ 16'

当我尝试使用Eclipse CDT构build程序时,我得到以下内容:

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

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

考虑以下Windows API级别的程序:

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

现在让我们使用GNU工具链(即g ++)来构build它,没有特殊的选项。 这里gnuc只是一个batch file,我使用它。 它只提供使g ++更为标准的选项:

 C:\ test> gnuc x.cpp

 C:\ test> objdump -x a.exe |  findstr / i“^子系统”
子系统00000003(Windows CUI)

 C:\ test> _

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

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

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

 C:\ test> gnuc x.cpp -mwindows

 C:\ test> objdump -x a.exe |  findstr / i“^子系统”
子系统00000002(Windows GUI)

 C:\ test> _

希望迄今为止,尽pipe-mwindows标志只是半logging文件。

如果没有这个半logging标志,那么必须更具体地告诉链接程序需要哪个子系统值,然后通常必须明确指定一些Windows API导入库:

 C:\ test> gnuc x.cpp -Wl, - 子系​​统,windows

 C:\ test> objdump -x a.exe |  findstr / i“^子系统”
子系统00000002(Windows GUI)

 C:\ test> _

这很好,GNU工具链。

但是,微软的工具链,即Visual C ++呢?

那么,构build一个控制台子系统可执行文件工作正常:

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

 C:\ test> dumpbin / headers x.exe | find/我“子系统”| find/我“Windows”
                3子系统(Windows CUI)

 C:\ test> _

但是,由于默认情况下,GUI子系统不能正常工作,

 C:\ test> msvc x.cpp user32.lib / link / subsystem:windows
 x.cpp
 LIBCMT.lib(wincrt0.obj):错误LNK2019:无法parsing的外部符号_WinMain @ 16在函数___tmainCRTStartu中引用
 p
 x.exe:致命错误LNK1120:1无法parsing的外部

 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/我“子系统”| find/我“Windows”
                2子系统(Windows GUI)

 C:\ test> _

没问题,但非常乏味。 如此神秘而隐藏的大多数Windows程序员,大多只使用微软的非标准默认工具,甚至不知道它,并错误地认为Windows GUI子系统程序“必须”具有非标准的WinMain而不是标准main 。 顺带一提,用C ++ 0x微软会遇到这个问题,因为编译器必须宣传它是独立的还是托pipe的(托pipe时它必须支持标准的main )。

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

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

那么可能是什么问题呢?

那么,你可能错过了一个main 。 而且你可能没有(适当的) WinMain ! 然后,g ++在search到main (没有这个)之后,而对于微软的非标准WinMain (没有这样的),报告说后者不见了。

testing一个空的来源:

 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 ):未定义的参考
转到“WinMain @ 16”
 collect2:ld返回1退出状态

 C:\ test> _

由Cheers和Hth总结上面的post。 – Alf,确保你定义了main()WinMain() ,g ++应该做正确的事情。

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

我在使用SDL编译我的应用程序时遇到了此错误。 这是由SDL在SDL_main.h中定义它自己的主函数引起的。 为防止SDL定义主函数,必须在包含SDL.h头文件之前定义SDL_MAIN_HANDLEDmacros。

尝试在构build之前保存您的.c文件。 我相信你的电脑正在引用一个没有任何信息的文件的path。

– 构buildC项目时遇到类似的问题