VS ERRORS及解决方法汇总

每次运行都提示项目过期

即使在没有对代码又任何修改的情况下,依然会提示项目已过期,可能解决方法如下:
1. 你修改过系统时间,某个文件的修改时间比当前实际时间晚,这样检查时每次都认为有已经修改的代码,所以需要编译,这种情况改一下文件的时间就可以了。
2. shashanzhao.com/archives/861.html
3. 不建议选择“不再显示此对话框”,这是掩耳盗铃的办法,编译器还是会编译,从而浪费时间。
4. 删除某些文件时只在硬盘上删除了,没有在VS的工程中删除导致的,这种情况就得找找看看是那个文件了,至少在VS的工程中删除对应的文件即可。

不显示某种warning

方法1:在代码中写#pragma warning (disable: ID);
方法2:编译选项里面有个disable specific warnings 输入ID;
方法3:某些特定的waring可以用宏关闭,比如4996可以使用_CRT_SECURE_NO_WARNINGS关闭警告4996。

C4996 This function or variable may be unsafe

线程安全错误,VS2008及以前是warning,从VS2010改成了error,使用宏_CRT_SECURE_NO_WARNINGS或者在文件前面使用#pragma warning (disable: 4996)都可以解决。

warning C4273:dll链接不一致

方法1: 选择项目->属性->预处理器->预处理定义, 增加:HYCOMMONWINAPI_EXPORTS
方法2:
就是在
ifdef HYCOMMONWINAPI_EXPORTS
define HYCOMMONWINAPI_API __declspec(dllexport)
else
define HYCOMMONWINAPI_API __declspec(dllimport)
endif
前面增加 #define HYCOMMONWINAPI_EXPORTS 其实这两种方法都是增加定义
方法3:在你的dll cpp文件中把
define HYCOMMONWINAPI_EXPORTS
加在#include <接口文件.h> 的前面
方法4:右击dll工程 — 属性,打开属性页,展开:配置属性 — C++ –预处理器,在预处理器定义的最后面填入:_AFXEXT,再次编译则搞定。

warning C4800: “BOOL”: 将值强制为布尔值“true”或“false”(性能警告)

在分配非 bool 值,或将此类值强迫到类型 bool 中时,将生成此警告。 通常,此消息是由于向 bool 变量分配 int 变量引起的,其中 int 变量仅包含 true 和 false 值,并可重新声明为 bool 类型。 如果您无法重写表达式以使用 bool 类型,则可以向该表达式中添加“!=0”,它可使表达式成为 bool 类型。 例如:PUM的PUMView中的CViewport类的
bool CViewport::IsGridShown()
{
return (m_vpStyle & VP_STYLE_GRID) != 0;
}
就可以使用该方法。
其实这个warning可以不去在意。查看对应的汇编文件,用的都是mov、cmp、setne这些不太耗时的指令。
bool a = false;
00C72F33 mov byte ptr [a],0
BOOL b = a;
00C72F37 movzx eax,byte ptr [a]
00C72F3B mov dword ptr [b],eax
bool c = b;
00C72F3E cmp dword ptr [b],0
00C72F42 setne al
00C72F45 mov byte ptr ,al
解决不解决这个warning对性能没什么影响,有洁癖的就修改一下好了。

无法打开预编译头文件[fatal error C1083: 无法打开预编译头文件:“Debug\***.pch”]

1. 在工程属性中的,配置属性->C/C++->预编译头->创建/使用预编译头的选项改成“创建预编译头”然后编译;
2. 编译工程;
3. 编译完后,不管编译是否成功,这个时候都可以将其再改成“使用预编译头”。
预编译头是VS提高编译速度的一种机制,有时候由于修改文件导致之前创建的预编译头不能使用或丢失,这个时候就重新创建一次就好了,但是只创建一次就可以,否则每次创建还不如不使用编译的快。
参考资料:http://blog.csdn.net/mplus/article/details/6137523

Warning C4251 需要有dll接口由class的客户端使用

这通常是由于以数据成员方式在DLL导出类中使用了模板类造成的。比如:
include <iostream>
include <vector>
using namespace std;
class __declspec( dllexport ) Test { public: std::vector<int> m_objCon; };
int main() {

return 0; }
这会导致这个警告: warning C4251: “Test::m_objCon”: class“std::vector<_Ty>”需要有 dll 接口由 class“Test”的客户端使用 1> with 1> [ 1> _Ty=int 1> ] 这个问题主要要描述的是不同的地方的vector的实现可能不一样所造成的问题。所以我们应该将其导出。有很多方法可以解决这个问题的。
第一种:将该数据改为指针方式: class __declspec( dllexport ) Test { public: std::vector<int>* m_objCon; }; 然后在构造函数和析构函数中分别初始化和释放它。 第二种: 将该模板类及其依赖类导出。
include <iostream>
include <vector>
using namespace std;
class __declspec( dllexport ) Test { public: template class __declspec( dllexport ) std::allocator<int>; template class __declspec( dllexport ) std::vector<int, std::allocator<int> >; public:
std::vector<int> m_objCon; };
int main() {

return 0; } 这种方法要注意的是必须要把要导出模板类的模板数据成员一并导出。有点类似于显式实例化。比如说你要导出boost::shared_ptr就还必须将其依赖的shared_count一并导出。导出map还需要导出对应pair等等。很麻烦啦~所以我们还是选择第四种吧。
第三种:Impl。
include <iostream>
include <vector>
using namespace std;
// 这些放到.h中 class Test_imp; class __declspec( dllexport ) Test { // 构造函数中初始化 析构中释放m_pImp; void test(); public: Test_imp* m_pImp; };
// 这个类放到cpp中去 class Test_imp { public: void test(){} std::vector<int> m_objCon; };
// 放到cpp中 void Test::test() { m_pImp->test(); }
int main() {

return 0; }

第三种除了可以解决上面的问题之外还可以隐藏代码,当然多了一个桥接的过程。
http://hi.baidu.com/dbfr2011818/item/b160d2f6c6c40ccd521c2606

该依赖项是由项目系统添加的,不能移除

ProjectDepends.png
有时候会有一些项目依赖项无法移除,出现如上图的提示,但是明明不需要依赖。这个时候可以把工程文件*.vcxproj用记事本打开,搜索到对应的工程名,然后将其移除,例如:
<ProjectReference Include=”..\PUMCore\PUMCore.vcxproj”>
<Project>{e7ac2d1e-f2f4-4af5-b2e3-ad9b02ca0688}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>

还有一种简单有效的办法:先把不能移除的依赖额工程从解决方案中删掉,然后再加进来,删掉的时候依赖关系肯定就没有了。
[编辑]无法打开**pdb,如同没有调试信息一样

这是由于没有找到对应库的调试信息文件pdb文件,或者文本版本不同,编译起打不开。
如果是因为版本不同,重新编译即可。如果是因为没有,应该是工程配置的问题。
如果是动态库,在链接器的调试中的生成调试信息改为是。
如果是静态库,在C/C++的输出文件中,程序数据库文件名由$(IntDir)vc$(PlatformToolsetVersion).pdb 改为$(IntDir)$(TargetName).pdb 就会和.lib生成在同一个目录了。

LINK : warning LNK4098: 默认库“LIBCMTD”与其他库的使用冲突;请使用 /NODEFAULTLIB:library

解决方法有2个:
1.右击工程 – 属性 ”配置属性 – 链接器 – 输入 – 忽略特定库“,添加 ”libcmt.lib“
2.右击工程 – 属性 ”配置属性 – 链接器 – 命令行” 添加: /NODEFAULTLIB:”libcmt.lib”
注意:在debug下为libcmtd.lib,和release版不一样。
参考资料:原理解析[1]

fatal error C1128: 节数超过对象文件格式限制: 请使用 /bigobj 进行编译

在 Visual Studio 开发环境中设置此编译器选项
打开项目的“属性页”对话框。 有关详细信息,请参见如何:打开项目属性页。
单击“C/C++”文件夹。
单击“命令行”属性页。
在“附加选项”框中键入编译器选项。
参考资料:http://msdn.microsoft.com/zh-cn/library/ms173499.aspx

Debug和Release结果不一致

1. 首先看工程配置是否一致;
2. 如果有数组、vector等结构,有可能release对一些代码做了优化(比如对一个数组做了操作,但是后面没有再用到它;或者在某些分支没有初始化一个变量就使用)。
3. 如果Debug运行正常而Release有run time error, 则很有可能是有数组越界或类似情况,也有可能是使用了未初始化的变量(比如指针为NULL甚至未初始化,或者其他变量没有初始化就使用)。http://stackoverflow.com/questions/12800777/visual-studio-2008-solution-release-version-runtime-fatal-error

4. 如果Debug结果正确而Release结果不正确,可能是因为变量没有初始化。Debug会自动初始化为NULL或0,而Release则不会初始化。http://stackoverflow.com/questions/1762088/common-reasons-for-bugs-in-release-version-not-present-in-debug-mode

5. 可能是一些在函数中使用++运算符导致的,如func(a++,a++),Debug和Release对两者优化方式不同。

error C2059: 语法错误:“常量”

1. const 常量和之前的宏冲突,比如在某个库中#define了PI,然后你自己的代码又写了const double PI=xxx,那么如果引用库在前就会出现该问题,即便你的定义有命名空间。解决方法就是在定义常量之前使用#undef PI。

fatal error C1853

这是由于在使用了预编译头的情况下混用C/C++导致的。一般会告诉你xxx.pch文件出错,那么一定是xx.pch文件对应的源文件使用了纯C语言的环境,导致无法启用预编译头。

找到xxx.cpp或者xxx.c文件(不要找xxx.h文件,.h文件不能设置),右键选择属性,找到C/C++,预编译头,选择不使用。重新生成该工程(一定要重新生成)。

重新生成之后不一定能彻底解决该问题,因为有可能该文件引用的工程中的文件还存在该问题。如果不出错则不用改,如果出错则继续根据错误改对应的文件。

运行时堆被损坏

“Windows 已在xxx.exe 中触发一个断点。

其原因可能是堆被损坏,这说明 xxx.exe 中或它所加载的任何 DLL 中有 Bug。

原因也可能是用户在 xxx.exe 具有焦点时按下了 F12。

输出窗口可能提供了更多诊断信息。”

  1. delete了一个不在堆上的变量。比如Class a; delete &a;出错的代码不会这么简单,如果某些函数参数为指针的情况使用变量的地址则有可能引发该错误。
  2. 内存访问越界。经常表现为数组或者字符串访问越界,尤其是字符数组越界导致没有终止符’\0’会严重影响其他变量的正常访问,也就是说编译器有可能在访问其他变量的时候出错,这种情况下很难找到罪魁祸首。这种情况下,如果越界的字节不太多,还会出现Debug版本不出错而Release版本出错的情况。
  3. stdafx.h文件中版本信息不符。
  4. 其他原因。

无法定位程序输入点于动态链接库xxx.dll

最常见的原因就是缺少xxx.dll,一般是因为使用了动态库的lib,却忘了添加其dll。

但是还有一种情况是:你添加了对应的dll,但是该dll还依赖了其他的dll,而报错的时候又不会说缺哪个dll(也许是因为封装的太好了)。

warning C4482: 使用了非标准扩展: 限定名中使用了枚举 

ENUM_TYPE et = ET_A;    // 这里如果写成ENUM_TYPE et = ENUM_TYPE::ET_A; 就会出现该warning

如上述代码所示,C/C++中的enum类型有点像批量typedef的感觉,除了定义数据类型的时候用的是enum类型名,使用的时候不需要在具体类型前面加enum名。不像C#、java等语言的用法。

error C4996

1>d:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility(2372): error C4996: ‘std::copy::_Unchecked_iterators::_Deprecate’: Call to ‘std::copy’ with parameters that may be unsafe – this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ ‘Checked Iterators’

注意:这个要加的宏不是“-D_SCL_SECURE_NO_WARNINGS”,而是“_SCL_SECURE_NO_WARNINGS”,这里写错了。估计是因为CMake的宏前面都有一个“-D”,就忘了删。

C++ keyword and

C++ 98就有了这个,但是VS一直不支持,还是得写&& https://en.cppreference.com/w/cpp/keyword/and

 

 

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

12 + 15 =