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


110

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

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

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

Answers:


183

考虑以下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”
子系统00000003(Windows CUI)

C:\ test> _

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

这也使命令解释器等待程序完成。

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

C:\ test> gnuc x.cpp -mwindows

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

C:\ test> _

希望到目前为止还可以,尽管该-mwindows标志只是半文档化的。

没有该半文档化标志的构建将不得不更具体地告诉链接器一个子系统想要的值,然后通常必须明确指定一些Windows API导入库:

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

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

C:\ test> _

使用GNU工具链,效果很好。

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

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

C:\ test> msvc x.cpp user32.lib
压缩文件

C:\ test> dumpbin / headers x.exe | 查找/ i“子系统” | 找到/ i“ Windows”
               3个子系统(Windows CUI)

C:\ test> _

但是,默认情况下,使用Microsoft的工具链作为GUI子系统进行构建时:

C:\ test> msvc x.cpp user32.lib / link / subsystem:windows
压缩文件
LIBCMT.lib(wincrt0.obj):错误LNK2019:函数___tmainCRTStartu中引用的未解析的外部符号_WinMain @ 16
p
x.exe:致命错误LNK1120:1个未解决的外部组件

C:\ test> _

从技术上讲,这是因为默认情况下, Microsoft的链接器对于GUI子系统是非标准的。默认情况下,当子系统为GUI时,Microsoft的链接器将使用运行时库入口点,即开始执行计算机代码的函数,该函数winMainCRTStartup调用Microsoft的non-standard WinMain而不是standard main

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

您要做的就是告诉Microsoft的链接器要使用哪个入口点,即mainCRTStartup哪个调用standard main

C:\ test> msvc x.cpp user32.lib / link / subsystem:windows / entry:mainCRTStartup
压缩文件

C:\ test> dumpbin / headers x.exe | 查找/ i“子系统” | 找到/ i“ Windows”
               2个子系统(Windows GUI)

C:\ test> _

没问题,但是非常乏味。而且如此神秘和隐藏,以至于大多数Windows程序员(大多只使用Microsoft的默认非标准工具)甚至都不知道它,并错误地认为Windows GUI子系统程序“必须”具有非标准WinMain而非标准main。顺便说一句,对于C ++ 0x,Microsoft会遇到问题,因为编译器随后必须宣传它是独立式的还是托管的(托管时,它必须支持standard main)。

无论如何,这就是g ++ 可能抱怨WinMain缺失的原因:这是Microsoft工具默认情况下对GUI子系统程序所要求的一种愚蠢的非标准启动功能。

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

那么可能是什么问题呢?

好吧,您可能缺少main。而且您可能也没有(适当)WinMain!然后,在搜索main(没有)和Microsoft的非标准(没有)之后,g ++ WinMain报告缺少后者。

使用空源进行测试:

C:\ test>输入nul> y.cpp

C:\ test> gnuc y.cpp -mwindows
c:/程序文件/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2 ):未定义的参考
ce到`WinMain @ 16'
collect2:ld返回1退出状态

C:\ test> _

3
@Alf P.Steinbach。非常感谢您的回复。至于All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main。有没有办法做到这一点,Eclipse CDT因为我没有使用命令行。感谢
简单性

1
@ user588855:由于您正在使用的g ++(可能)不适用于您。仅适用于末尾的部分(可能)。也就是说,定义一个main或一个WinMain,或确保相关文件包含在项目中。干杯,
干杯和健康。-Alf

@Alf P.Steinbach。您定义main或是winmain什么意思?谢谢
简单性

1
我刚刚制作了一个名为main.cpp的文件,其代码为:int main(){}
实际上是

3
如果每个下选民都可以解释下选民,我将很高兴。因为可能其他读者也有相同的误解(无论是什么意思),然后我们才能消除这种误解。每个人都会受益,而不是被误导。因此,请说明您的反对意见。谢谢。
干杯和健康。-Alf

68

总结以上由Cheers和hth发表的文章。-阿尔夫,请确保您有main()WinMain()定义和g ++应该做正确的事情。

我的问题是main()偶然在名称空间中定义的。


刚刚意识到所有这些重要的事情。就我而言,由于未声明任何参数(argc,argv),因此未找到main()。添加后,它找到了main。而且,这种工作方式的性质意味着mingw试图通过提供自己的main(依次称为WinMain)来提供帮助。GUI程序仅具有WinMain,而mingw中的主存根用于到达那里。如果您有一个主电源,那么它将使用它。
杰夫·缪尔

extern“ C” int main(void)为我解决了这个问题
–dryler

33

使用SDL编译应用程序时遇到此错误。这是由SDL在SDL_main.h中定义其自己的主要功能引起的。为了防止SDL定义主要功能,必须在包含SDL.h标头之前定义SDL_MAIN_HANDLED宏。


好答案!+1
Mohammad Kanan

非常感谢!此命令有效:gcc main.c -I“ E:\ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64-mingw32 \ include” -I“ E:\ Libs \ SDL2_ttf- devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ include“ -L” E:\ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64- mingw32 \ lib“ -L” E:\ Libs \ SDL2_ttf-devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ lib“ -lSDL2 -lSDL2main -lSDL2_ttf -o app.exe
5Observer8

5

生成之前,请尝试保存.c文件。我相信您的计算机正在引用文件中没有任何信息的路径。

-建立C专案时发生类似的问题


这实际上解决了我的问题,我在此发表评论以帮助它吸引更多关注。
David Chen,

0

检查所有文件都包含在您的项目中:

更新cLion之后,我弹出了同样的错误。经过数小时的修改,我发现我的文件之一没有包含在项目目标中。将其添加回活动项目后,我停止获取对winmain16的未定义引用,并编译了代码。

编辑:在您的IDE中检查构建设置也是值得的。

(不确定此错误是否与最近更新了IDE有关-可能是因果关系,也可能只是相关关系。请对该要素的任何见解发表评论!)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.