LNK2019:在函数___tmainCRTStartup中引用了未解析的外部符号_main

29

我遇到了以下错误:

LNK2019:在函数___tmainCRTStartup中引用了未解析的外部符号_main

有很多帖子与此错误相关,但是其中没有一个解决方案适用于我。并且,也没有一个解释为什么会出现这个错误。

我尝试过:

  • 在链接器属性中使用wWinMainCRTStartup作为入口点(线程)
  • 将链接器设置为“Windows”(与上述相同的线程)
  • 右键单击解决方案名称->添加->现有项->具有主体文件(与上述相同的线程)
  • #include <tchar.h>(error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup)
  • 尝试项目+属性、C/C++、代码生成、缓冲区安全性检查=否(线程)
  • 选项:C/C++、代码生成、运行时库=/MTd;C/C++、代码生成、基本运行时检查=默认;C/C++、代码生成、缓冲区安全性检查=否;链接器、高级、入口点=main(线程)
  • 注释掉main.cpp中的头文件,除了using namespace std#include <iostream> - 结果是从引用这些头文件的函数中逐步产生错误。
  • 我删除了除测试代码以外的所有内容,并排除了除main.cpp之外的所有源文件;正如预期的那样,它可以工作,这是朝着正确方向迈出的一小步。问题肯定出在其中一个头文件中。
  • 使用Win32 Windows应用程序模板创建新项目(线程线程)。
  • 我还没有尝试过,但怀疑这些也不会起作用:

    • 使用int main()(不确定它们是指文件名还是主函数名)(线程)
    • 在Windows 7 x64上使用cmake进行构建(线程)。

    我为什么会收到此错误消息,有什么解决方法?


    1
    你有一个 int main(char** argv, int argc) 函数吗? - Linuxios
    3
    @Linuxios,正确的函数原型是“int main(int argc, char** argv)”,你的顺序有误。 - BlakBat
    1
    @BlakBat:谢谢。抱歉,我根本不在Windows上工作,但这是到处都有的签名。唉。 - Linuxios
    12个回答

    31
    你的项目类型是什么?如果是"Win32项目",你的入口点应该是(w)WinMain。如果是"Win32控制台项目",则应该是(w)main。名称_tmain被定义为mainwmain,具体取决于是否定义了UNICODE。
    如果是DLL,则为DllMain
    可以在项目属性,链接器,系统,子系统下看到项目类型。它会显示"控制台"或"Windows"。
    请注意,入口点名称因是否定义UNICODE而异。在VS2008中,默认情况下已经定义。
    正确的main原型应该是:
    int _tmain(int argc, _TCHAR* argv[])
    
    或者
    int _tmain()
    

    确保它是其中之一。

    编辑:

    如果你在 _TCHAR 上遇到错误,请添加一个

    #include <tchar.h>
    
    如果你认为问题出在其中一个头文件上,那么请进入包含 main() 函数的文件属性,在预处理器下启用生成预处理文件。然后编译。你会得到一个相同名称但扩展名为 .i 的文件。打开它,看看是否对 main() 函数发生了什么不好的事情。理论上可能会有恶意的 #define。
    编辑2:
    如果定义了 UNICODE(这是默认设置),链接器将期望入口点是 wmain(),而不是 main()。 _tmain 的优势是与 UNICODE 无关 - 它可以转换为 main 或 wmain。
    以前有一个原因来维护 ANSI 构建和 Unicode 构建。Windows 95/98/Me 中的 Unicode 支持非常不完整。主要 API 是 ANSI,并且仅在这里和那里存在 Unicode 版本,但并不普遍。此外,VS 调试器无法显示 Unicode 字符串。在 NT 内核 OSes 中(即 Windows 2000/XP/Vista/7/8/10),Unicode 支持是主要的,ANSI 函数被添加在其之上。因此,自 VS2005 以来,项目创建的默认值是 Unicode。这意味着 wmain。他们不能保留相同的入口点名称,因为参数类型不同。_TCHAR 被 #定义为 char 或 wchar_t。因此,_tmain 是 main(int argc, char **argv) 或 wmain(int argc, wchar_t **argv)。
    你之前可能在某个时候会因为没有将 argv 的类型更改为 _TCHAR** 而在 _tmain 处遇到错误。
    如果你不打算支持 ANSI(可能不需要),你可以将入口点重新组织为
    int wmain(int argc, wchar_t *argv[])
    

    并删除 tchar.h 的头文件包含行。


    int _tmain(int argc, _TCHAR* argv[]) 导致错误 C2061:语法错误:标识符“_TCHAR”;我尝试了使用 int main(int argc, char** argv) 的变化,但返回了初始的 lnk2019 错误。 - forest.peterson
    如果我删除除#include <iostream>之外的所有头文件,并注释掉除测试行以外的所有文本,则可以编译此代码,因此问题似乎在其中一个头文件中 - 如何跟踪导致lnk2019主错误的头文件问题的过程是什么? - forest.peterson
    2
    如果你在 _TCHAR 上遇到了错误,请加入 #include <tchar.h>。另外,请查看我的编辑。 - Seva Alekseyev
    那个方法可行。我没有使用一些我参考的线程中提到的#include <tchar.h>来建立连接,也没有使用int _tmain(int argc, _TCHAR* argv[])。你能解释一下这些函数的功能是什么吗?为什么int main()有问题,需要这些其他的东西呢? - forest.peterson
    我们说通过给答案点赞来表达赞同 :) - Seva Alekseyev
    显示剩余2条评论

    6
    因为还没有提及,这对我来说是解决方案:
    在创建项目的新配置后,我的 DLL 出现了这个错误。我不得不转到“项目属性->配置属性->常规”并将“配置类型”更改为“动态库(.dll)”。
    因此,如果您尝试其他方法仍然遇到问题,那么检查配置类型是否符合您的项目预期是值得的。如果未正确设置,编译器将寻找错误的主要符号。在我的情况下,它正在寻找 WinMain 而非 DllMain。

    3

    当我试图关闭控制台应用程序项目中的预编译头文件并删除头文件stdafx.h时,出现了以下错误:

    要解决此问题,请转到项目属性 -> 链接器 -> 子系统,并将值更改为未设置

    在您的主类中,使用其他人已经提到的标准C ++ main函数原型:

    int main(int argc, char** argv)
    

    2
    如果您有一个“Win32项目”+定义了WinMain,并且您的SubSystem链接器设置为WINDOWS,但如果有人将链接器设置中的“附加选项”设置为“/SUBSYSTEM:CONSOLE”(看起来这个附加设置优先于实际的SubSystem设置),仍然可能会出现此链接器错误。

    1

    当我不小心将wmain放在命名空间中时,出现了这个错误。wmain不应该在任何命名空间中。此外,我在使用的一个库中有一个main函数,而VS从那里获取了main函数,这使得情况更加奇怪。


    我敢打赌这在很多情况下都是问题所在。 - livin_amuk

    1

    我发现当我选择选项:项目->属性->链接器->系统->子系统->控制台(/subsystem:console),并且确保包含以下函数: int _tmain(int argc,_TCHAR* argv[]){return 0} 编译、链接和运行都将顺利进行。


    请确保包含tchar.h头文件。 - Shania
    这对我也起作用了。事实上,当子系统“未设置”时,它也可以工作。 - user2799508

    1
    我刚刚遇到了这个问题。当我在main()定义中添加'extern "C"'时,问题消失了。
    奇怪的是,我昨天写的另一个简单程序几乎相同,没有extern "C",但编译时没有出现这个链接器错误。
    这让我觉得问题可能是一些微妙的设置,在某些配置对话框深处可以找到,并且'extern "C"'并不真正解决潜在问题,但表面上使事情正常工作。

    0
    在我的情况下,是因为我无意中删除了头文件部分中的stdafx.htargetver.h文件,而不是删除它们。将这些文件添加回头文件部分,问题就解决了。
    我有这些文件:
    #pragma comment( linker, "/entry:\"mainCRTStartup\"" ) // set the entry point to be main()
    

    我只需要加上注释(在前面加上//),就可以了。


    0

    我以前遇到过这个问题,但是已经解决了。主要的问题是我错误地拼写了 int main() 函数。我写成了 int mian()....干杯!


    1
    这个答案太针对你自己了。由于在OP的问题中没有拼错main,所以没有理由认为这是问题所在。 - lwassink
    1
    OP没有展示任何源代码,他只是陈述了错误。今天我也遇到了同样的错误,但后来发现我拼错了单词“main”,所以在更正后错误消失了。 - Serign Modou Bah

    0

    这个main函数在Linux和Windows上都可以工作 - 我是通过试错和他人的帮助找到的,所以无法解释为什么它能工作,但它确实可以 int main(int argc, char** argv)

    不需要tchar.h

    这里是维基百科上相同的答案Main function


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