vs常见错误详解Word格式文档下载.docx

上传人:b****6 文档编号:21522346 上传时间:2023-01-31 格式:DOCX 页数:9 大小:23.89KB
下载 相关 举报
vs常见错误详解Word格式文档下载.docx_第1页
第1页 / 共9页
vs常见错误详解Word格式文档下载.docx_第2页
第2页 / 共9页
vs常见错误详解Word格式文档下载.docx_第3页
第3页 / 共9页
vs常见错误详解Word格式文档下载.docx_第4页
第4页 / 共9页
vs常见错误详解Word格式文档下载.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

vs常见错误详解Word格式文档下载.docx

《vs常见错误详解Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《vs常见错误详解Word格式文档下载.docx(9页珍藏版)》请在冰豆网上搜索。

vs常见错误详解Word格式文档下载.docx

就这样改:

CodeGeneration->

MultithreadDLL

“Linking...

 

nafxcwd.lib(thrdcore.obj):

unresolvedexternalsymbol__endthreadex

unresolvedexternalsymbol__beginthreadex

libcd.lib(crt0.obj):

unresolvedexternalsymbol_main”

VC++默认的工程设置是单线程的,而你使用了多线程,所以要修改设置。

选择菜单“Project|settings”,选择C/C++标签,在CODEGENERATION分类中选择除SINGLE-THREADED的其他选择。

其他:

1.解决errorLNK2005:

___crtExitProcess已经在LIBCMTD.lib(crt0dat.obj)中定义

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

典型的例子,就是因為c++runtimelibrary設定不同,所造成的重複定義連結錯誤.

而另一個常見的例子是專案與library使用不同的字元集合設定

(如:

一個用UnicodeCharacterSet,另一個用Multi-ByteCharacterSet)

這個錯誤

發生原因,有可能是

1.你link的lib使用C++Multi-threadedDLL(/MD)

2.而你的source使用的C++runtimelibrary是Multi-threaded(/MT)

導致重複定義

解決方法:

兩個使用相同的C++runtimelibrary.

例如都使用static的Multi-threaded(/MT).

2.错误1errorLNK2005:

"

private:

__thiscalltype_info:

:

type_info(classtype_infoconst&

)"

(?

?

0type_info@@AAE@ABV0@@Z)已经在LIBCMT.lib(typinfo.obj)中定义MSVCRTD.lib

项目->

属性->

c/C++ 

->

代码生成 

运行时库 

设置为:

多线程调试DLL(/MDd)

被引用的库和调用的程序编译选项不同,需要改成一致后编译

3.#pragmaonce与#ifndef的区别

为了避免同一个文件被include多次

#ifndef方式

#pragmaonce方式

在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。

方式一:

#ifndef__SOMEFILE_H__

#define__SOMEFILE_H__

......//一些声明语句

#endif

方式二:

#pragmaonce

#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。

当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况

#pragmaonce则由编译器提供保证:

同一个文件不会被包含多次。

注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。

带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。

对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。

当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。

方式一由语言支持所以移植性好,方式二可以避免名字冲突

4.errorLNK2019:

无法解析的外部符号__imp__PathCombineW

PathCombine是Shellapi需要引入库

#pragmacomment(lib,"

shlwapi.lib"

5. 

errorC2662:

MyClass:

GetName()”:

不能将“this”指针从“constMyClass”转换为“MyClass&

boolMyClass:

operator==(constMyClass*n1)const

{

returnGetName()==n1->

GetName();

}

原因是不能在const函数中调用对象的非const方法,MyClass中的GetName()必须是const的。

6.template模板

搞死了

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

7.errorC2275:

“MyClass”:

将此类型用作表达式非法MyClass.Instance();

原因:

Instance是静态方法,用.引用会出错。

应该是MyClass:

Instance()

8.errorLNK2019:

无法解析的外部符号"

public:

__thiscallMyClass(void)

只声明了构造函数,MyClass();

,但未定义。

可以定义空函数,或者直接注释掉,使用默认构造函数。

9. 

errorC2504:

“testing”:

未定义基类

classPackToolTest:

testing.Test{}

Test是testing命名空间下的一个类,需要用域操作符,testing:

Test

还有一个问题,缺少基类继承权限(public、protected、private)

10.errorC2864:

“MyClass:

_nullpack”:

只有静态常量整型数据成员才可以在类中初始化 

classMyClass{

string_nullpack="

test"

;

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

11.errorLNK2019:

无法解析的外部符号 

_WinMain@16 

intmain()

由于创建的是Win32Project,和Win32consoleProject的链接库不同

方法1:

在程序最开始的地方加上以下语句

#pragma 

comment(linker, 

/subsystem:

console"

方法2:

project 

>

setting 

在link 

的project 

options 

中将/subsystem:

windows(console)删了

12.类似“已经在msvcprtd.lib(MSVCP80D.dll)中定义”问题

vs2005Debug/Release需要分别配制

分析一下错误来源,会发现:

1. 

错误来源主要是重复定义的问题,而且重复定义的基本上都是VCRuntime和StandardC++Library中的函数

2. 

LIBCMT和LIBCPMT为Release下的Lib,本来不应该出现在Debug版本的链接的Lib中

3. 

重复定义的问题主要出现在:

LIBCMT,LIBCPMT,MSVCPRTD,MSVCRTD

来看看出问题的LIB是那些:

LIBCMT:

CRuntime库的多线程静态链接的Release版本

LIBCPMT:

C++StandardLibrary的多线程静态链接的Release版本

MSVCPRTD:

C++StandardLibrary的多线程DLL的Debug版本

4. 

MSVCRTD:

CRuntimeLibrary的多线程DLL的Debug版本

当前我们的配置是多线程DLL的Debug版,因此3和4是应该出现在link的列表中的,不属于多余。

而后两者则是只是当多线程静态链接Release版中才会出现。

这提示我在项目中加入的ANTLR.LIB可能是造成这个问题的根源,因为静态库的编译选项很容易和主程序发生冲突,并且根据实际信息我们可以看出ANTLR.LIB应该是用多线程静态链接的Release版本来编译的。

解决方法:

1、首先查看编译项目依赖的其他项目的运行时库是否一致

2、如果不一致,改为同样的运行时库,如在下编译的是:

“多线程调试DLL(/MDd)”,现在需要把所有的依赖项目的运行时库都改为一致的库,就OK了。

13. 

errorC2143:

语法错误:

缺少“;

”(在“*”的前面)

产生错误处,某类型未include,可能头文件名拼写错误、头文件名已更改

14.errorC2572:

Invoke”:

重定义默认参数:

参数2

stringMyClass:

Invoke(constCParam&

paraObj,INVOKETYPEtype=ASYN)

默认参数,只需在声明时指定。

方法定义的时候无需指定默认参数。

paraObj,INVOKETYPEtype/*=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:

fatalerrorCVT1100:

重复的资源。

type:

MANIFEST,name:

1,language:

0x0409

另一个则提示为:

LINK:

fatalerrorLNK1123:

转换到COFF期间失败:

文件无效或损坏

已经到了链接期,应该说,问题就不像编译通不过那么别扭了,而查阅MSDN关于这两个问题的说明,终于找到了解决的方法,现简单的陈述如下:

首先,出现这两个问题的原因都是一个,即文件中的现有资源文件和新资源字符串表ID冲突。

微软也给出了解决这个问题的方法,但是,在现有的情况下,这个方法是靠不住的,因为,不可能不使用wx.rc资源。

所以,一个变通的解决方法就是:

工程属性->

配置属性->

清单工具->

输入和输出->

嵌入清单,选择[否],即可。

warningLNK4099:

PDB原因及解决方案

0x00现象及原因

举例:

warningLNK4099:

PDB'

wxbase30ud.pdb'

wasnotfoundwith'

wxbase30ud.lib(any.obj)'

使用VC时链接了三方静态库,并且三方静态库(一般是开源的三方库)是在一个solution下的多个project,当然,网上基本都是这么回答的,其实本质原因是因为这些开源库一般都会通过各种方式修改solution和project的默认路径把二进制生成到同一个目录下,比如lib,而我们自己平时简单的静态库工程是不怎么修改默认工程配置的. 

由于每个开源库的作者有自己的工程组织方式,但导致LNK4099的最终原因无非是PDB路径问题

0x01解决方案

a.如果确认不需要PDB,即不需要调试开源库,完全可以在设置里将/Zi或/ZI去掉,这样即能消除warning也能提升开源库编译速度

b.如果需要调试开源库,方法也不复杂

b.1.将开源库project里的C/C++->

General->

DebugInformationFormat设置为Zi或ZI(两者区别请自行google,Zi就够用了,只是高版本的VS默认都是ZI)

b.2.然后在C/C++->

OutputFiles->

PragramDatabaseFileName设置为$(OutDir)$(TargetName).pdb,(有些2B开源库这里设置的跟VS默认的是一样的比如$(IntDir)vc$(PlatformToolsetVersion).pdb,但把IntDir改成了同一个目录,每个project生成出来的pdb名字路径都是一致的,当然就会出问题),这里需要注意的是,一定要确保$(OutDir)$(TargetName)是有意义的,个别开源库完全不用vs自带的宏,甚至个别开源库需要configure之后才生产vcproject,甚至是绝对路径,但你所要确保的是,目录必须跟生成的.lib是同一个,文件名(不包括扩展名)必须是和生成的xxx.lib的xxx是一致的.之后你要做的就是把每个project的debug&

release都按照如上改好再编译就ok了

0x02不在一个solution

如果静态链接库的project不与你的主project在一个solution下面,那么你的主solution调用静态链接库时想看到库的调试信息,那么必须保证库的vc80.pdb以及.obj文件的目录存在且没有改变。

0x03总结

其实这个问题完全不是编译器或VS的事(这也说明了即使你disable4099waning依然还会报,因为压根跟编译没关系),就是路径错了,改对就ok了.

网上绝大多数回答要不然就是跑题告诉你如何如何屏蔽不显示这个warning,要不就是让你把obj目录拷过去(这个没用)等等,都没鸟用

Error:

Lnk2005调用多个外部链接库时必须使用相同的运行时库(/MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题,l)

一、MD(d)、MT(d)编译选项的区别

1、编译选项的位置

以VS2005为例,这样子打开:

1) 

打开项目的PropertyPages对话框

2) 

点击左侧C/C++节

3) 

点击CodeGeneration节

4) 

右侧第六行RuntimeLibrary项目

2、各个设置选项代表的含义

编译选项

包含

静态链接的lib

说明

/MD

_MT、_DLL

MSVCRT.lib

多线程、Release、DLL版本的运行时库

/MDd

_DEBUG、_MT、_DLL

MSVCRTD.lib

多线程、Debug、DLL版本的运行时库

/MT

_MT

LIBCMT.lib

多线程、Release版本的运行时库

/MTd

_DEBUG、_MT

LIBCMTD.lib

多线程、Debug版本的运行时库

简单的说:

(1)/MD,表示运行时库由操作系统提供一个DLL,程序里不集成。

(2)/MT,表示运行时库由程序集成。

二、/MD、/MT的选择

1、为什么选择/MD,不选/MT?

(1)程序就不需要静态链接运行时库,可以减小软件的大小;

(2)所有的模块都采用/MD,使用的是同一个堆,不存在A堆申请,B堆释放的问题;

  (3)用户机器可能缺少我们编译时使用的动态运行时库。

(补充:

如果我们软件有多个DLL,采用/MT体积增加太多,则可以考虑/MD+自带系统运行时库)

2、为什么选择/MT,不选择/MD?

(1)有些系统可能没有程序所需要版本的运行时库,程序必须把运行时库静态链接上。

   

(2)减少模块对外界的依赖。

3、多个模块,必须选择相同的运行时库。

三、选择/MT需要解决的堆空间释放问题

不同的模块各自有一份C运行时库代码、或者根本没有C运行时库,导致了各个模块会有各自的堆。

如果在A堆中申请空间,到B堆中释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。

附录的DLL以及DLLUser代码,以STL的string为例,通过修改编译选项验证了这个问题。

string在赋值的时候需要释放掉原来的内存空间,然后再申请新的内存空间存储新的内容,如果跨模块了,释放的时候就存在“A模块申请B模块释放”的问题,导致程序崩溃。

  (跨模块释放内存导致崩溃的内容,在《windows核心编程》第五版Page511谈DLL和进程的地址空间时有谈到)

四、选择/MD需要注意多个模块使用不同版本运行时库的问题

(2012-9-17补充)

(2013.5.30补充)

 

多个dll被一个exeLoadLibrary加载,如果这些dll使用的运行时库是不同的,那么可能出现加载失败,原因可能是旧版本的运行时库已经在了,而某个dll它需要的是新版本的运行时库,旧版本不符合要求。

如果工程里所有的模块都是自己写的或者可以完全控制的,那么这个问题不难解决,只需要在工程设置里都设置/MD,然后在相同的环境下编译一次就行。

但是假如这个模块是外界提供的呢?

可能存在这种情况:

A动态库使用了B静态库,B静态库使用了C动态库,B静态库是外界提供的,我们要使用它,但无法修改它,我们也无法接触到C动态库。

如果C动态库使用的运行时库版本跟编译A动态库的本地使用的不一致,那么A动态库里的嵌入信息就会记录两个不同版本的运行时库,它被加载的时候,可能会选择版本新的。

假设A动态库被一个exeLoadLibrary加载,而这个exe本身的运行时库是旧的,这样就会导致A动态库加载失败,即便把新的运行时库拷贝到目录下也不行,因为exe这个进程已经加载了那个旧的运行时库。

这时候必须使用manifest文件指定嵌入到A动态库里的运行时库为某个版本,忽略掉C动态库使用的运行时库版本。

这个问题挺复杂的,我心思没去验证windows的PE文件加载会对运行时库做什么样的优先选择、运行时库在静态库里的记录…。

只要记住,给外界使用的组件版本尽量避免使用/MD(这样会导致膨胀吗?

据说,安装包可以做字节流式压缩)。

  附上另一个问题:

静态库的依赖关系:

exe-->

libA-->

libB,现在不想让exe接触到libB,于是把libA的librarian选项-->

General选项-->

LinkLibraryDependencies设置为Yes,这样即可,libA会包含libB,exe只需要接触libA。

另外需要特别注意,libA对libB的依赖只需要且只能在Solution的ProjectDependencies里设置,如果在libA的代码里写了”#pragmacomment(lib,"

libB.lib"

)”,会导致exe在linklibA的时候提示找不到libA。

如果exe还出现link错误,那一定是VS抽筋了:

五、参考资料

1、微软关于MT、MD等的详细介绍

2、不要出现A模块申请,B模块释放的情况

3、运行时库有哪些版本

4、CSDN上关于堆空间释放的讨论

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1