警告 C26407
首选范围内的对象,请勿进行不必要的堆分配 (r.5)
为了避免不必要地使用指针,我们尝试检测本地分配的常见模式。 例如,我们检测调用运算符 new
的结果是否存储在局部变量中以及随后是否被显式删除。 此检查支持 C++ 核心准则规则 R.5:首选作用域对象,切勿不必要的进行堆分配。 要解决此问题,请使用 RAII 类型而不是原始指针,并允许 RAII 类型处理资源。 显然,没有必要创建包装器类型来分配单个对象。 相反,对象类型的局部变量效果会更好。
注解
为了减少警告的数量,代码分析只检测所有者指针的这种模式。 因此,有必要首先正确标记所有者。 如果我们从客户那里收到有关 Visual Studio C++ 开发人员社区的反馈以支持此类方案,我们可以轻松地将此分析扩展为涵盖原始指针。
“作用域对象”这个术语可能有点误导作用。 一般来说,我们建议你使用自动管理其生命周期的局部变量,或有效管理动态资源的智能对象。 智能对象可以进行堆分配,但在代码中并不明确。
如果警告在数组分配时触发(动态缓冲区常需要),你可以使用标准容器或
std::unique_pointer<T[]>
。仅针对局部变量检测模式。 在以下情况下不会发出警告:将某一分配先分配给全局变量,然后在同一个函数中删除。
代码分析名称:DONT_HEAP_ALLOCATE_UNNECESSARILY
示例 1:堆中不必要的对象分配
auto tracer = new Tracer();
ScanObjects(tracer);
delete tracer; // C26407
示例 2:堆中不必要的对象分配(用本地对象修复)
Tracer tracer; // OK
ScanObjects(&tracer);
示例 3:堆中不必要的缓冲区分配
auto value = new char[maxValueSize];
if (ReadSetting(name, value, maxValueSize))
CheckValue(value);
delete[] value; // C26407
示例 4:堆中不必要的缓冲区分配(由容器修复)
auto value = std::vector<char>(maxValueSize); // OK
if (ReadSetting(name, value.data(), maxValueSize))
CheckValue(value.data());