使用geti()函数触发Warning C6385警告的原因咨询
首先,我们来拆解你遇到的C6385警告:
Warning C6385 Reading invalid data from 'snapPts': the readable size is '((geti()+1))*sizeof(DPoint3d)' bytes, but '48' bytes may be read.
这个警告是Visual Studio的静态代码分析工具(启用了Microsoft Mixed(C++/CLR) Recommended Rules)发出的,核心意思是:它检测到你的代码可能会读取超出分配范围的内存。
为什么用geti()会触发警告,用局部变量i不会?
问题出在静态分析工具对「值的确定性」的判断上:
当你用
int i = 2时,分析工具可以明确知道i的值是2,并且在if(i>1)分支里,i肯定满足大于1的条件。此时你分配的内存是(2+1)*sizeof(DPoint3d)(也就是3个DPoint3d对象,总大小72字节),而访问snapPts[1]只需要读取第2个对象(24字节,加上前面的24字节总共48字节),完全在分配的内存范围内,所以工具判断这是安全的,不会发出警告。当你直接调用
geti()时,虽然你现在写的函数是固定返回2,但静态分析工具不会假设这个函数的返回值是恒定的。它会做最坏情况的假设:比如如果geti()返回0,那(0+1)*sizeof(DPoint3d)只分配1个DPoint3d(24字节),此时访问snapPts[1]就需要读取从第24字节开始的24字节,总共48字节——这明显超出了分配的内存大小,于是工具触发警告提醒你可能存在的越界风险。
如何解决这个警告?
这里有几个简单的方案,你可以根据实际情况选择:
将函数返回值赋值给局部变量
把geti()的结果存到一个局部变量里,让静态分析工具能跟踪到这个值的确定性:int val = geti(); if (val > 1) { DPoint3d* snapPts = (DPoint3d *)_alloca((val + 1) * sizeof(DPoint3d)); DPoint3d* snapPts2 = new DPoint3d(); *snapPts2 = snapPts[1]; }这样工具能确认
val的值是2,就不会再警告了。把函数声明为
constexpr(如果返回值确实固定)
如果geti()的返回值在编译期就能确定,给它加上constexpr修饰,让编译器和分析工具都知道这是一个常量:constexpr int geti() { return 2; }添加断言约束返回值范围
如果geti()的返回值可能变化,但你能保证它一定大于等于1,可以用断言来告诉分析工具这个前置条件:#include <cassert> // ... int val = geti(); assert(val >= 1); // 确保val+1 >=2,这样访问snapPts[1]是安全的 if (val > 1) { DPoint3d* snapPts = (DPoint3d *)_alloca((val + 1) * sizeof(DPoint3d)); DPoint3d* snapPts2 = new DPoint3d(); *snapPts2 = snapPts[1]; }
内容的提问来源于stack exchange,提问作者Irshad Babar

