当我尝试使用Eclipse CDT
构建程序时,我得到以下内容:
/mingw/lib/libmingw32.a(main.o),此:main.c中:(文本+ 0x106): 未定义的引用`WinMain @ 16
为什么?而且,我该如何解决这个问题?
答案 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有关-可能是因果关系,也可能只是相关性。请对该要素发表任何见解!)