常见编译/链接错误及其解决办法

来源:互联网 发布:免费发送短信软件 编辑:程序博客网 时间:2024/05/17 22:34

转载地址:http://blog.csdn.net/cc198877/article/details/8057524

这个有几个解决错误的方法比较有用。

1. 解决error LNK2005: ___crtExitProcess 已经在 LIBCMTD.lib(crt0dat.obj) 中定义

有的時候, 在 Debug 模式下編譯沒問題, 換到 Release 模式就發生一堆問題.

典型的例子, 就是因為 c++ runtime library 設定不同, 所造成的重複定義連結錯誤.
而另一個常見的例子是 專案與 library 使用不同的字元集合設定
(如: 一個用 Unicode Character Set, 另一個用 Multi-Byte Character Set)

這個錯誤
發生原因, 有可能是
1. 你 link 的 lib 使用 C++ Multi-threaded DLL (/MD)
2. 而你的 source 使用的 C++ runtime library 是 Multi-threaded (/MT)
導致重複定義

解決方法:
兩個使用相同的 C++ runtime library.
例如都使用 static 的 Multi-threaded (/MT).


2. 错误 1 error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) 已经在 LIBCMT.lib(typinfo.obj) 中定义 MSVCRTD.lib

项目 -> 属性 -> c/C++  -> 代码生成  -> 运行时库  设置为: 多线程调试 DLL (/MDd) 
被引用的库和调用的程序编译选项不同,需要改成一致后编译


3. #pragma once与 #ifndef的区别
为了避免同一个文件被include多次
1   #ifndef方式
2   #pragma once方式
在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。
    方式一: 
    #ifndef __SOMEFILE_H__
    #define __SOMEFILE_H__
    ... ... // 一些声明语句
    #endif

    方式二:
    #pragma once
    ... ... // 一些声明语句
    #ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况
    #pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
   方式一由语言支持所以移植性好,方式二 可以避免名字冲突

 

4. error LNK2019: 无法解析的外部符号 __imp__PathCombineW
PathCombine是Shell api需要引入库
#pragma comment( lib, "shlwapi.lib")

 

5.  error C2662: "MyClass::GetName()”: 不能将“this”指针从“const MyClass”转换为“MyClass &” 
bool MyClass::operator==(const MyClass* n1) const
{
 return GetName() == n1->GetName();
}
原因是不能在const函数中调用对象的非const方法,MyClass中的GetName()必须是const的。


6. template 模板
搞死了

模板声明和定义必须在同一个文件中,而且只有实例话模板类型时才编译模板实例

 

7. error C2275: “MyClass”: 将此类型用作表达式非法 MyClass.Instance();
 原因:Instance是静态方法,用.引用会出错。应该是MyClass::Instance()

 

8. error LNK2019: 无法解析的外部符号 "public: __thiscall MyClass(void)
原因:只声明了构造函数,MyClass(); ,但未定义。 可以定义空函数,或者直接注释掉,使用默认构造函数。

 

9.  error C2504: “testing”: 未定义基类 
class PackToolTest : testing.Test {}
原因:Test是testing命名空间下的一个类,需要用域操作符,testing::Test
还有一个问题,缺少基类继承权限(public、protected、private)

 

10. error C2864: “MyClass::_nullpack”: 只有静态常量整型数据成员才可以在类中初始化  
class MyClass {

      string _nullpack = "test";

}

原因:c++ 中,成员变量不能在声明时初始化,而是在构造函数初始化列表中先初始化

 

11. error LNK2019: 无法解析的外部符号 _WinMain@16 int main()
原因:由于创建的是Win32 Project,和Win32 console Project的链接库不同
方法1:在程序最开始的地方加上以下语句 
#pragma   comment(linker,   "/subsystem:console ") 
方法2:project   > >   setting   > >   在link   的project   options   中将/subsystem:windows(console)删了 

 

12.类似“已经在 msvcprtd.lib(MSVCP80D.dll) 中定义”问题
vs2005 Debug /Release需要分别配制

分析一下错误来源,会发现:
1.     错误来源主要是重复定义的问题,而且重复定义的基本上都是VC Runtime和Standard C++ Library中的函数
2.     LIBCMT和LIBCPMT为Release下的Lib,本来不应该出现在Debug版本的链接的Lib中
3.     重复定义的问题主要出现在:LIBCMT, LIBCPMT, MSVCPRTD, MSVCRTD
来看看出问题的LIB是那些:
1.     LIBCMT:C Runtime库的多线程静态链接的Release版本
2.     LIBCPMT:C++ Standard Library的多线程静态链接的Release版本
3.     MSVCPRTD:C++ Standard Library的多线程DLL的Debug版本
4.     MSVCRTD:C Runtime Library的多线程DLL的Debug版本
当前我们的配置是多线程DLL的Debug版,因此3和4是应该出现在link的列表中的,不属于多余。而后两者则是只是当多线程静态链接Release版中才会出现。这提示我在项目中加入的ANTLR.LIB可能是造成这个问题的根源,因为静态库的编译选项很容易和主程序发生冲突,并且根据实际信息我们可以看出ANTLR.LIB应该是用多线程静态链接的Release版本来编译的。
解决方法:
   1、首先查看编译项目依赖的其他项目的运行时库是否一致
   2、如果不一致,改为同样的运行时库,如在下编译的是:“多线程调试 DLL (/MDd)”,现在需要把所有的依赖项目的运行时库都改为一致的库,就OK了。

   3,项目-属性-链接器-输入-忽略特定默认库:  MSVCRTD.lib (根据具体报错信息选择要忽略的库)

 

13.  error C2143: 语法错误 : 缺少“;”(在“*”的前面)
原因:产生错误处,某类型未include,可能头文件名拼写错误、头文件名已更改

 

14. error C2572: “MyClass::Invoke”: 重定义默认参数 : 参数 2 
string MyClass::Invoke(const CParam& paraObj, INVOKETYPE type = ASYN)

原因:默认参数,只需在声明时指定。方法定义的时候无需指定默认参数。
string MyClass::Invoke(const CParam& paraObj, INVOKETYPE type /*= ASYN*/)

{ ... }

 

15. 错误 C2558 没有可用的复制构造函数或复制构造函数声明为“explicit”
试图复制其复制构造函数为 private 的类。在大多数情况下,不应复制具有 private 复制构造函数的类。通用编程技术声明 private 复制构造函数以防止直接使用类。该类本身可能无用,或需要另一个类才能正常工作。

尝试复制其复制构造函数为 explicit 的类。用 explicit 声明复制构造函数会阻止将类的对象传递到函数或从函数返回类的对象。

原因: 拷贝构造函数、赋值函数参数必须用const修饰

 

16. 不能创建抽象类对象
原因: 1. 存在虚函数未实现; 2. 由于疏忽重载虚函数格式错误(此问题需要仔细检查才能发现); 3. 虚函数名称与系统中已有的虚函数重名,导致重载失败(这点很纳闷)。

 

17. 没有找到MSCRV80D.dll

工程属性: 配置类型 由 exe 改成 lib 后生成, 然后再改回来
运行时会出现 “没有找到MSCRV80D.dll” 的异常

解决方法: 
工程属性:MFC的使用 由 “使用标准Windows库” 改成 “在静态库中使用MFC“ 生成 ,然后再改回来
生成、运行 OK

 

18. CVTRES : fatal error CVT1100: 重复的资源。type:MANIFEST, name:1, language:0x0409
另一个则提示为:
LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

已经到了链接期,应该说,问题就不像编译通不过那么别扭了,而查阅MSDN关于这两个问题的说明,终于找到了解决的方法,现简单的陈述如下:
首先,出现这两个问题的原因都是一个,即文件中的现有资源文件和新资源字符串表 ID 冲突。微软也给出了解决这个问题的方法,但是,在现有的情况下,这个方法是靠不住的,因为,不可能不使用wx.rc资源。所以,一个变通的解决方法就是:
工程属性->配置属性-> 清单工具->输入和输出->嵌入清单,选择[否],即可。


19. 已加载“C:WindowsSystem32tdll.dll”,Cannot find or open the PDB file

VS2010开发环境,源程序正确,也生成了.exe,却不能顺利运行。运行后情况如下,请问是怎么回事啊。。。
“陈森.exe”: 已加载“H:\vs2010\练习\陈森\Debug\陈森.exe”,已加载符号。
“陈森.exe”: 已加载“C:\Windows\System32\ntdll.dll”,Cannot find or open the PDB file
“陈森.exe”: 已加载“C:\Windows\System32\kernel32.dll”,Cannot find or open the PDB file
“陈森.exe”: 已加载“C:\Windows\System32\KernelBase.dll”,Cannot find or open the PDB file
“陈森.exe”: 已加载“C:\Windows\System32\user32.dll”,Cannot find or open the PDB file
“陈森.exe”: 已加载“C:\Windows\System32\gdi32.dll”,Cannot find or open the PDB file
“陈森.exe”: 已加载“C:\Windows\System32\lpk.dll”,Cannot find or open the PDB file
“陈森.exe”: 已加载“C:\Windows\System32\usp10.dll”,Cannot find or open the PDB file
“陈森.exe”: 已加载“C:\Windows\System32\msvcrt.dll”,Cannot find or open the PDB file

满意回答
你随便写一个helloworld就会出现这个Cannot find or open the PDB file,就是找不到什么问题。

这样解决:工具--》选项--》》调试--》符号
接下来就是勾选Microsoft ,然后确认,重新编写一个程序,什么也可以,看看是不是好了?
看到此目录下符号缓存了吗?找到这个目录拷贝出来,找个地方存放。

接下来就是去掉Microsoft符号服务器,要是不去,每次都要从Microsoft下载很麻烦,已经缓存了,我们就可以利用好这些缓存,至此完美解决。



20. 

windows已在xxx.exe中触发一个断点,其原因可能是堆被损坏,这说明**.exe中或它所加载的任何DLL中有bug。 

原因也可能是用户在xx.exe具有焦点时按下了F12。输出窗口可能提供了更多诊断信息 。
    当碰到此种错误的时候,基本上是因为我们在编写程序的时候,在处理数组或者指针的时候出现了越界(最可能)或者超长
的情况,从而导致了对栈堆的损坏。

(但我的程序中,将dll和exe项目的属性都改为MD/MDD,然后程序就运行了,参考了以下内容)

写了个程序,在DLL中用malloc分配了一块内存,但是在exe程序中释放,结果程序crash,原因就是:
其原因可能是堆被损坏,这也说明 TestMySticker.exe 中或它所加载的任何 DLL 中有 bug。
想了半天以为是自己的写法有问题,后终于在google上找 到了原因,汗。。。

以下文字引用自 http://hi.baidu.com/huhe/blog/item/0b422edd1f1563d98c1029a3.html
很 感谢作者的分析

一个模块一个堆,一个线程一个栈。
dll里malloc的内存,在exe里free会出错。

CRT(C运行时期库)不是使用进程缺省的堆来实现malloc(new中调用malloc)的,而是使用一个全局句柄 HANDLE _crtheap来分配内存的。这个_crtheap是在XXXCRTStartUp(CRT提供的进口点函数)中创建的。 
由于CRT静态连接,则楼主的DLL里有也有一个CRT,因此也有一个_crtheap。而在dll中的new使用dll中的_crtheap句柄分配 堆,在exe中的delete使用exe中的_crtheap释放堆,当然失败!

解决办法:
1。在DLL中输出一个函数给EXE调用,专门用来释放由DLL分配的内存;
2。用 GlobalAlloc()代替new,用GlobalFree()代替delete;
3。使用单一的堆,分配内存使用 HeapAlloc(GetProcessHeap(),0,size),释放内存使用HeapFree(GetProcessHeap(),0,p);
4。 把dll和exe的Settings的C/C++选项卡的Code   Generation的Use   Run-time   liberary改成Debug   Multithreaded   DLL,在Release版本中改成Multithreaded   DLL;这样使用一个CRT了——MSVCRT.DLL。

以下是CSDN上的讨论,同样讨论的很详细了
http://topic.csdn.net/t/20031009/17/2338051.html

以上是在网上找到的资料,今天做过详细测试,结果如下:

测试1:使用malloc/free组合来分配和释放内存,DLL中使用 malloc分配,exe中使用free释放。
我建的是Win32 DLL工程, C/C++->Code generation 设置是 Multithread DLL debug, 但是exe工程设置是MultiThread debug,所以不管怎么样,总是会抛异常. 这就间接证明了上述的描述是正确的, 若我修改exe工程设置是 MultiThread DLL debug, 那么malloc/free组合就能很好的工作起来了。

测试2:使用HeapAlloc/HeapFree组合来分配和释放内存,DLL 中使用HeapAlloc分配,exe中释放。
exe的配置还是MultiThread Debug,DLL中HeapAlloc(GetProcessheap(), HEAP_ZERO_MEMORY, 1024)分配,exe中HeapFree(GetProcessHeap(), 0, p)释放,,则还是无法正常运行,还是抛异常。若exe中设置成MultiThread DLL debug就正常运行了。

测试3:还是 使用HeapAlloc/HeapFree来进行,但是DLL中导出一个方法来释放DLL中分配的内存。
若exe配置是MultiThread Debug,无法正常运行,抛异常。若修改成MultiThread DLL debug正常运行。

所以得到的结论如下:
不管 是使用malloc/free组合还是HeapAlloc/HeapFree组合,exe工程均需要设置成MultiThread DLL debug才能正常运行起来的,CSDN上的那个讨论在这儿貌似是由出入的,而且DLL的设置不能随意修改。所以若有涉及到这种问题的,最好的办法还是在 哪个模块分配的就在哪个模块释放最好,要不然反倒会引来更多的麻烦。

from

http://blog.csdn.net/blz_wowar/archive/2008/03/13/2176536.aspx

       上面这文章是我在找“...其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug。”解决办法的时候找到的,学到一点,呵呵。可惜我那工程的直接原因并不是因为上面所说的(也许间接原因是),我的工程里是开启一个UI线程,UI 线程中有一个view,结果单步调试时报错“...其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug。”,最后解决办法是,view需要用new创建,不能直接通过create来创建,原因是view应该是建在堆上

==========

VC项目属性→配置属性→C/C++→代码生成→运行时库 可以采用的方式有:多线程(/MT)、多线程调试(/MTd)、多线程DLL(/MD)、多线程调试DLL(/MDd)、单线程(/ML)、单线程调试(/MLd)

Reusable Library Switch Library Macro(s) Defined Single Threaded /ML LIBC (none) Static MultiThread /MT LIBCMT _MT Dynamic Link (DLL) /MD MSVCRT _MT and _DLL Debug Single Threaded /MLd LIBCD _DEBUG Debug Static MultiThread /MTd LIBCMTD _DEBUG and _MT Debug Dynamic Link (DLL) /MDd MSVCRTD _DEBUG, _MT, and _DLL

    其中以小写“d”结尾的选项表示的DEBUG版本的,没有“d”的为RELEASE版本。大型项目中必须要求所有组件和第三方库的运行时库是统一的,否则将会出现LNK2005井喷。

    单线程运行时库选项/ML和/MLd在VS2003以后就被废了。

    /MT和/MTd表示采用多线程CRT库的静态lib版本。该选项会在编译时将运行时库以静态lib的形式完全嵌入。该选项生成的可执行文件运行时不需要运行时库dll的参加,会获得轻微的性能提升,但最终生成的二进制代码因链入庞大的运行时库实现而变得非常臃肿。当某项目以静态链接库的形式嵌入到多个项目,则可能造成运行时库的内存管理有多份,最终将导致致命的“Invalid Address specified to RtlValidateHeap”问题。另外托管C++和CLI中不再支持/MT和/MTd选项。

    /MD和/MDd表示采用多线程CRT库的动态dll版本,会使应用程序使用运行时库特定版本的多线程DLL。链接时将按照传统VC链接dll的方式将运行时库MSVCRxx.DLL的导入库MSVCRT.lib链接,在运行时要求安装了相应版本的VC运行时库可再发行组件包(当然把这些运行时库dll放在应用程序目录下也是可以的)。 因/MD和/MDd方式不会将运行时库链接到可执行文件内部,可有效减少可执行文件尺寸。当多项目以MD方式运作时,其内部会采用同一个堆,内存管理将被简化,跨模块内存管理问题也能得到缓解。

    结论:/MD和/MDd将是潮流所趋,/ML和/MLd方式请及时放弃,/MT和/MTd在非必要时最好也不要采用了。

选项 说明

/MD

使应用程序使用运行时库的多线程并特定于 DLL 的版本。定义 _MT 和 _DLL,并使编译器将库名 MSVCRT.lib 放入 .obj 文件中。

用此选项编译的应用程序静态链接到 MSVCRT.lib。该库提供允许链接器解析外部引用的代码层。实际工作代码包含在 MSVCR80.DLL 中,该库必须在运行时对于与 MSVCRT.lib 链接的应用程序可用。

当在定义了 _STATIC_CPPLIB (/D_STATIC_CPPLIB) 的情况下使用 /MD 时,它将导致应用程序与静态多线程标准 C++ 库 (libcpmt.lib) 而非动态版本 (msvcprt.lib) 链接,同时仍通过 msvcrt.lib 动态链接到主 CRT。

/MDd

定义 _DEBUG、_MT 和 _DLL,并使应用程序使用运行时库的调试多线程并特定于 DLL 的版本。它还使编译器将库名 MSVCRTD.lib 放入 .obj 文件中。

/MT

使应用程序使用运行时库的多线程静态版本。定义 _MT 并使编译器将库名 LIBCMT.lib 放入 .obj 文件中,以便链接器使用 LIBCMT.lib 解析外部符号。

/MTd

定义 _DEBUG 和 _MT。此选项还使编译器将库名 LIBCMTD.lib 放入 .obj 文件中,以便链接器使用 LIBCMTD.lib 解析外部符号。

/LD

创建 DLL。

将 /DLL 选项传递到链接器。链接器查找 DllMain 函数,但并不需要该函数。如果没有编写 DllMain 函数,链接器将插入返回 TRUE 的 DllMain 函数。

链接 DLL 启动代码。

如果命令行上未指定导出 (.exp) 文件,则创建导入库 (.lib);将导入库链接到调用您的 DLL 的应用程序。

将 /Fe(命名 EXE 文件)解释为命名 DLL 而不是 .exe 文件;默认程序名成为 basename.dll 而不是 basename.exe。

除非显式指定 /MD,否则将暗指 /MT。

/LDd

创建调试 DLL。定义 _MT 和 _DEBUG。


1-18转自 http://blog.csdn.net/powerlly/article/details/4409592        

19参考 

 http://zhidao.baidu.com/question/317285600.html&__bd_tkn__=21ab70273b2193274659a96ae4af28fe91458efa8078338d51fed8133ea5c69d362ad36bb4bcda3b39bb3949f6bbe47087ac3af56e60b1f4e7eb60157b5dfa309562aff85e0f03de0125277ad641bc7f3c75ed040d5abf8ddb4e407e75214128ca157e314ec1a5dfe90bfcaccbdc8c0bcd3421ff48ae

20参考 http://hi.baidu.com/cr0_3/item/a99ddd4ed79178e01f19bc66

http://www.cnblogs.com/wintergrass/archive/2011/11/09/2243780.html


0 0