LIBCMT.LIB(crt0.obj) : error LNK2001: unresolved external symbol _main 错误解决

本文介绍了在编译ATL工程Release版时遇到的链接错误“unresolved externalsymbol_main”的原因及解决方法。错误源于预处理器定义了_ATL_MIN_CRT导致服务器未链接CRT启动代码。文章提供了三种解决方案,并解释了不同编译配置的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接错误"unresolved external symbol _main"

Article last modified on 2002-3-2

------------------------------------------------------------

The information in this article applies to:

  - Microsoft ATL 2.X

------------------------------------------------------------

现象:
当你编译一个ATL工程的Release版时,你得到了下面这个链接错误:

   LIBCMT.LIB(crt0.obj) : error LNK2001: unresolved external symbol _main

如下图所示:


    而Debug版本的编连却顺利通过。
 

 

原因与解决方法:
出错原因:
如果你在工程中使用了CRT函数,而这些函数又需要CRT启动代码,就会出现这种链接错误。默认情况下,Release配置的Preprocessor definitions中定义了_ATL_MIN_CRT,它将CRT启动代码从你的EXE或DLL剔出去了。

 

 

背景知识:
1:

ATL支持把一个服务器编连优化成最小尺寸或者依赖性最小。我们可以定义三个预处理器符号来影响服务器的优化。

_ATL_MIN_CRT             服务器不链接标准的C/C++运行库

_ATL_DLL                  服务器动态链接工具函数库atl.dll

_ATL_STATIC_REGISTRY    服务器静态链接对组件注册的支持

如果定义了预处理器符号_ATL_MIN_CRT,那么我们的服务器不链接C/C++运行库,并且ATL提供了函数malloc、realloc、new和delete的一个实现。当定义了这个符号时,我们不能调用任何其他的C/C++运行库的函数。否则,就会受到这样的待遇:

LIBCMT.LIB(crt0.obj) : error LNK2001: unresolved external symbol _main

ATL向导生成的ATL工程为所有的Release版本的编连定义了_ATL_MIN_CRT,但是没有为Debug版本定义这个符号。

Debug配置没有定义这三个符号中的任何一个。

RelMinSize配置定义了_ATL_MIN_CRT和_ATL_DLL。

RelMinDependency配置定义了_ATL_MIN_CRT和_ATL_STATIC_REGISTRY。

 

2:

C Run-Time Library (without iostream)
 Characteristics
 Option
 Defined
 
LIBC.LIB
 a statically linked library for single-threaded programs

(Single threaded, static link)
 /ML
 
 
LIBCMT.LIB
 a statically linked library that supports multithreaded programs

(Multithreaded, static link)
 /MT
 _MT
 
MSVCRT.LIB
 Multithreaded, dynamic link (import library for MSVCRT.DLL)
 /MD
 _MT, _DLL
 

 

解决方法:
 

下面方法中的任何一个都可以纠正这个错误:

Ø         去除_ATL_MIN_CRT这个预处理符号;

Ø         打开stdafx.cpp,注释掉#include <atlimpl.cpp>这句话,然后编译,即可;

Ø         在工程的配置对话框的Link页面上,"ignore libraries"编辑框中输入Libcmt.lib,然后编译,如下图所示:


你将会得到几个“unresolved external”的错误,如下所示。


        这个列表就是你用到的CRT的函数。

Look for things that you think may be pulling in the startup code and remove them if you can.Instead, use their Win32 equivalents. For example, use lstrcmp() instead of strcmp(). Known functions that require CRT startup code are some of the string and floating point functions.

其他:
我的VC IDE是6.0版本和SP5,如果用ATL COM AppWizard创建Service (EXE)工程。在这种情况下,它的RelMinDependency版本的配置中就没有定义_ATL_MIN_CRT符号!这和微软声称的“Service EXE Created with ATL COM AppWizard Doesn't Build in Release Mode”不一样,可能这是一个已经被FIX了的Bug。

 

 

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/richie12/archive/2010/08/09/5799097.aspx

LIBC.lib(crt0dat.obj) : error LNK2005: __cinit already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: _exit already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __exit already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __cexit already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __c_exit already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __C_Exit_Done already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __C_Termination_Done already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __exitflag already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __wpgmptr already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __pgmptr already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: ___winitenv already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __wenviron already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: ___initenv already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __environ already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: ___wargv already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: ___argv already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: ___argc already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __winminor already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __winmajor already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __winver already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __osver already defined in libcmt.lib(crt0dat.obj) LIBC.lib(crt0dat.obj) : error LNK2005: __umaskval already defined i
最新发布
03-13
<think>嗯,用户遇到了Visual Studio中的LNK2005错误,提示在LIBC.liblibcmt.lib中有多个符号定义。我需要先理解这个错误的常见原因。根据引用[3],这个错误通常是因为同一个符号被多次定义,而链接器不知道用哪个。可能的情况是运行时库的冲突,比如同时链接了静态库的不同版本,如libc.liblibcmt.lib。 接下来,用户提到具体涉及LIBC.liblibcmt.lib,这让我想到可能是项目中有混合使用了不同版本的运行时库。比如,有些模块用了多线程静态库(libcmt.lib),而其他模块可能用了单线程的(libc.lib)或者动态链接的DLL版本(如msvcrt.lib)。这时候链接器会发现同样的函数在多个库中存在,导致重复定义。 根据引用[1],这些库是不同运行时库的静态链接版本。解决方案应该是统一项目的运行时库设置。例如,在项目属性中,C/C++ -> 代码生成 -> 运行时库,确保所有依赖项都使用相同的选项,比如多线程调试(/MTd)或者多线程(/MT),避免混合使用/MT和/MD。 另外,引用[4]提到的/VERBOSE链接器选项和DUMPBIN工具可以帮助查看具体引用了哪些符号和库。用户可能需要检查是否有第三方库或模块使用了不同的运行时库设置,导致冲突。需要确保所有库都是用相同配置编译的。 还有可能的情况是用户手动添加了这些库,导致重复。需要检查链接器输入的附加依赖项,移除不必要的库引用。同时,确保没有在代码中使用#pragma comment(lib, ...)重复引入不同的运行时库。 总结下来,解决步骤应该是:统一运行时库设置,检查第三方库的兼容性,清理多余的库引用,使用工具分析符号冲突的具体位置。</think>### 解决Visual Studio LNK2005错误:符号重复定义问题 #### 问题分析 LNK2005错误通常是由于符号(如函数、变量)在多个库或目标文件中被重复定义引起的。当链接器发现同一符号在`LIBC.lib`和`libcmt.lib`等不同运行时库中存在时,会触发此错误。根本原因是**运行时库的混合使用**,例如同时链接了静态库(`libcmt.lib`)和动态库(`msvcrt.lib`)的不同版本[^1][^3]。 --- #### 解决步骤 1. **统一运行时库设置** - 在Visual Studio中,依次打开: **项目属性 → C/C++ → 代码生成 → 运行时库** 确保所有依赖项(包括主项目和第三方库)使用**相同的运行时库类型**: - 多线程调试(`/MTd`) - 多线程(`/MT`) - 动态调试(`/MDd`) - 动态(`/MD`) *注意:静态库(`/MT`/`MTd`)与动态库(`/MD`/`MDd`)不可混用[^3]。* 2. **检查第三方库的兼容性** - 若使用第三方库(如`.lib`文件),需确认它们是否与当前项目的运行时库设置一致。例如: - 若主项目使用`/MTd`,所有第三方库也需用`/MTd`编译。 - 若不一致,需重新编译第三方库或调整主项目配置。 3. **清理多余的库引用** - 在**项目属性 → 链接器 → 输入 → 附加依赖项**中,移除显式添加的`LIBC.lib`、`libcmt.lib`等库。默认情况下,VS会根据运行时库设置自动链接对应的库。 4. **使用工具定位冲突** - **方法1**:通过链接器的`/VERBOSE`选项查看详细链接过程: ```bash # 在项目属性 → 链接器 → 命令行 → 附加选项中添加 `/VERBOSE` ``` - **方法2**:用`DUMPBIN`工具分析符号定义: ```bash # 查看库中的符号定义 dumpbin /SYMBOLS your_library.lib # 检查动态库的导出符号 dumpbin /EXPORTS your_dll.dll ``` 这有助于定位重复符号的具体来源[^4]。 --- #### 示例场景 假设主项目使用`/MTd`(多线程调试静态库),但引用了某个第三方库`ThirdParty.lib`(使用`/MDd`编译)。此时链接器会同时加载`libcmt.lib`(对应`/MTd`)和`msvcrt.lib`(对应`/MDd`),导致符号重复。解决方案是重新用`/MTd`编译`ThirdParty.lib`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值