未定义的引用`WinMain @ 16'

Sim*_*ity 103 c++ eclipse eclipse-cdt

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

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

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

Che*_*Alf 174

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

#define NOMINMAX
#include <windows.h>

int main()
{
    MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Run Code Online (Sandbox Code Playgroud)

现在让我们使用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子系统程序"必须"具有非标准WinMain而不是标准main.顺便说一下,使用C++ 0x Microsoft将会遇到此问题,因为编译器必须广告它是独立的还是托管的(托管时它必须支持标准main).

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

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

那可能是什么问题呢?

好吧,你可能错过了一个main.你可能也没有(正确)WinMain!然后g ++,搜索main(没有这样),并为微软的非标准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> _

  • @Alf P. Steinbach.非常感谢您的回复.至于`你所要做的就是告诉微软的链接器使用哪个入口点,即mainCRTStartup,它调用标准的main`.有没有办法做"Eclipse CDT",因为我没有使用命令行.谢谢 (2认同)
  • 如果每个downvoter能解释downvote,我会很高兴.因为可能其他读者有同样的误解(无论是什么),然后我们可以清除它.每个人都会受益,而不是被误导.所以,请解释你的downvote.谢谢. (2认同)

Tim*_*ski 64

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

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


小智 27

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


小智 9

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