未定义对 `WinMain@16' 的引用

131

当我尝试使用Eclipse CDT构建程序时,出现以下错误:

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): undefined reference to `WinMain@16

为什么会出现这个错误?如何解决这个问题?


3
尝试保存您的文件并重新运行,在我的情况下它有效了。 - yugsharma1711
在我的情况下,这是一个没有int main() {}函数的文件。 - undefined
7个回答

202

当链接器找不到WinMain函数时,就会出现这个错误,因此很可能是缺失了该函数。在您的情况下,您可能也缺少了main函数。

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

#define NOMINMAX
#include <windows.h>

int main()
{
    MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
现在我们使用GNU工具链(即g++)构建它,无需特殊选项。这里的gnuc只是我用来提供选项以使g++更加标准的批处理文件。
这意味着链接器默认生成控制台子系统可执行文件。文件头中的子系统值告诉Windows程序需要哪些服务。在这种情况下,使用控制台系统意味着程序需要一个控制台窗口。这也导致命令解释程序等待程序完成。
现在让我们使用GUI子系统进行构建,这意味着程序不需要控制台窗口。希望到目前为止都没问题,尽管-mwindows标志只是半文档化的。
如果没有该半文档化标志,则需要更明确地告诉链接器所需的子系统值,并且通常必须明确指定一些Windows API导入库。
使用Microsoft工具链构建控制台子系统可执行文件可以正常工作。但是,默认情况下,使用Microsoft的工具链构建GUI子系统就不起作用。
这实际上是因为Microsoft的链接器默认情况下对于GUI子系统而言是非标准的。当子系统为GUI时,Microsoft的链接器使用名为winMainCRTStartup的运行时库入口点,该函数调用Microsoft的非标准WinMain而不是标准的main。
不过,解决这个问题很简单。只需告诉Microsoft的链接器要使用哪个入口点,即mainCRTStartup,它会调用标准的main。没有问题,但非常繁琐。
对于缺少main的问题,你可能确实缺少一个main,也可能没有(正确的)WinMain。然后g++在查找main(没有这样的函数)和Microsoft的非标准WinMain(没有这样的函数)之后报告后者缺失。
因此,这就是为什么g++有时会抱怨缺少WinMain的原因:Microsoft的工具链默认情况下需要一个愚蠢的非标准启动函数,用于GUI子系统程序。

3
@Alf P. Steinbach, 非常感谢您友好的回复。关于“你所要做的就是告诉Microsoft的链接器使用哪个入口点,即mainCRTStartup,它调用标准的main函数”,在不使用命令行的情况下,是否有方法可以在Eclipse CDT中实现这一点呢?谢谢。 - Simplicity
1
由于你正在使用g++,所以这可能不适用于你。 只有最后一部分(可能)适用。也就是说,定义一个“main”或“WinMain”,或者确保相关文件已包含在项目中。干杯! - Cheers and hth. - Alf
@Alf P. Steinbach。您所说的定义mainwinmain是什么意思?谢谢 - Simplicity
@user588855:答案顶部的示例程序展示了一种标准的main函数。你需要在你的程序中加入它(但是需要添加其他内容)。或者你可以使用非标准的微软WinMain,但是你必须要有其中之一,并且文件需要被包含在项目中。 - Cheers and hth. - Alf
1
我刚刚创建了一个名为main.cpp的文件,其中包含以下代码: int main() { } - Indeed
显示剩余6条评论

84

总结上述Cheers、hth和Alf的帖子。确保您已经定义了main()WinMain(),并且g++应该会做正确的事情。

我的问题是main()无意中被定义在命名空间内。


刚刚意识到一些重要的事情。在我的情况下,它没有找到main()函数,因为我没有声明任何参数(argc,argv)。一旦添加了这些参数,它就找到了main函数。此外,这种工作方式的本质意味着mingw试图通过提供自己的main函数来帮助调用WinMain函数。GUI程序只有WinMain函数,mingw中的main存根用于到达WinMain函数。如果您有一个main函数,则会使用该函数代替mingw中的main函数。 - Jeff Muir
extern "C" int main(void) 对我解决了问题。 - driedler
@driedler basic.start.main - “它的类型应该具有C++语言链接,并且它应该具有已声明类型为整数型的返回类型,但除此之外,其类型是由实现定义的。” - 因此,如果您需要使用C链接,则可能存在问题。 - Ted Lyngmo

37

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


非常感谢!这个命令是有效的: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 - 8Observer8

16

在编译之前尝试保存你的.c文件。我相信你的电脑正在引用一个没有内容的文件路径。


4

我的情况是我没有主函数。


0

我也遇到了同样的问题。为了解决它,我在构建之前点击保存来保存我的.c文件。我相信我的电脑正在引用一个没有信息的文件路径。


-1

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

我在更新cLion后遇到了同样的错误。经过数小时的调试,我注意到我的一个文件未被包含在项目目标中。将其添加回活动项目后,我不再收到winmain16未定义的引用错误,并且代码编译成功。

编辑:还值得检查IDE中的构建设置。

(不确定此错误是否与最近更新IDE有关 - 可能是因果关系或简单相关性。欢迎评论任何有关该因素的见解!)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接