2011-03-10 100 views
89

当我尝试使用Eclipse CDT建立一个程序,我得到如下:未定义的参考`的WinMain @ 16'

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

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

回答

158

考虑下面的Windows API级的程序:

#define NOMINMAX 
#include <windows.h> 

int main() 
{ 
    MessageBox(0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND); 
} 

现在,让我们使用GNU工具链构建它(即G ++),没有特殊的选项。这里gnuc只是一个批处理文件,我使用它。它只提供的选项,使克++多个标准:

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

然而,与微软的工具链建设作为GUI子系统默认情况下不工作:

 
C:\test> msvc x.cpp user32.lib /link /subsystem:windows 
x.cpp 
LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol [email protected] referenced in function ___tmainCRTStartu 
p 
x.exe : fatal error LNK1120: 1 unresolved externals 

C:\test> _ 

从技术上讲,这是因为微软’ s链接器对于GUI子系统默认为非标准。默认情况下,当子系统GUI,那么微软的链接器使用运行时库切入点,其中机器代码开始执行的功能,称为winMainCRTStartup,调用微软的非标准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 /i "subsystem" | find /i "Windows" 
       2 subsystem (Windows GUI) 

C:\test> _ 

没问题,但很繁琐。大多数Windows程序员大多只使用微软的非标准默认工具,甚至不知道它,并且错误地认为Windows GUI子系统程序“必须”必须有非标准WinMain而不是标准main。顺便说一句,在C++ 0x的情况下,微软会遇到这样的问题,因为编译器必须宣传它是独立的还是托管的(托管时它必须支持标准main)。

无论如何,这是为什么G ++ 可以抱怨WinMain丢失:它是微软的工具需要通过默认GUI子系统程序的傻非标准启动功能。

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

那么会有什么问题呢?

那么,你可能是失踪 a 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 `[email protected]' 
collect2: ld returned 1 exit status 

C:\test> _ 
+2

@Alf P. Steinbach。非常感谢您的回复。至于''你所要做的就是告诉微软的链接器使用哪个入口点,即mainCRTStartup,它调用标准main'。有没有办法做'Eclipse CDT',因为我没有使用命令行。谢谢 – Simplicity 2011-03-10 14:06:53

+1

@ user588855:因为你使用的是g ++(可能)不适用于你。只有最后(可能)的部分适用。也就是说,定义一个'main'或'WinMain',或者确保相关文件包含在项目中。欢呼声, – 2011-03-10 14:42:37

+0

@Alf P. Steinbach。定义'main'或'winmain'是什么意思?谢谢 – Simplicity 2011-03-10 15:07:59

50

总结的欢呼和HTH上述职位。 - Alf,确保你有main()WinMain()定义和g ++应该做正确的事情。

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

+0

刚刚意识到这一切重要的事情。在我的情况下,它没有找到main(),因为我没有声明任何参数(argc,argv)。一旦添加,它发现主要。此外,这种工作方式的性质意味着mingw通过提供自己的主体来尝试提供帮助,而主体又调用WinMain。 GUI程序只会有WinMain,并且mingw中的主存根被用来到达那里。如果你有一个主,那么它使用它。 – 2016-03-23 00:53:36

15

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

1

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

- 建设C项目时存在类似问题