未定义的引用`WinMain @ 16'

时间:2011-03-10 12:41:33

标签: c++ eclipse eclipse-cdt

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

  

/mingw/lib/libmingw32.a(main.o),此:main.c中:(文本+ 0x106):   未定义的引用`WinMain @ 16

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

7 个答案:

答案 0 :(得分:169)

考虑以下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工具链可以正常工作。

但是微软的工具链,即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

但是,没有什么大不了的。

您所要做的就是告诉Microsoft的链接器使用哪个入口点,即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子系统程序“必须”具有非标准{{1而不是标准WinMain。顺便说一句,使用C ++ 0x Microsoft会遇到问题,因为编译器必须宣传它是独立的还是托管的(托管时它必须支持标准main)。

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

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

那可能是什么问题?

好吧,你可能缺少一个main。你可能也没有(正确的)main!然后g ++在搜索了WinMain(没有这样的话)之后,以及微软的非标准main(没有这样的话),报告后者丢失了。

使用空来源进行测试:

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

答案 1 :(得分:59)

总结上述帖子,干杯和赫斯。 - Alf,确保定义了main()WinMain(),g ++应该做正确的事情。

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

答案 2 :(得分:24)

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

答案 3 :(得分:1)

尝试在构建之前保存.c文件。我相信你的计算机正在引用一个文件的路径,里面没有任何信息。

- 在构建C项目时遇到类似问题

答案 4 :(得分:1)

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

答案 5 :(得分:1)

有同样的问题。为了修复它,我在构建之前单击了保存以保存我的 .c 文件。我相信我的计算机引用了一个文件路径,其中没有任何信息。

答案 6 :(得分:0)

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

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

编辑:同样值得在IDE中检查构建设置。

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