CL.FMM
使用不相符的函数释放内存
类级别检查器会根据 Scott Meyer 的高效 C++ 规则类构造来生成建议。
CL.FMM 基于 Scott Meyer 的第 5 项:使用 new和 delete 的相应用法中的相同形式。此检查器可查找使用一种机制分配并使用另一种机制释放的内存;例如,将 C 和 C++ 内存管理函数混合,或将标量和矢量内存管理函数混合。
漏洞与风险
当内存使用 C++ new 运算符进行分配,并使用 C 运行时函数 free() 解除分配时,此检查器将暴露出最典型的问题。在这种情况下,无论该内存中可能驻留有何种对象,都不会调用 C++ 析构函数,因此尽管完全可以解除分配该内存,但执行此操作时将不包含程序员的预期语义。
此外,如果不同的 C 和 C++ 实现使用不同的底层堆,混用函数很容易导致内存泄漏和堆损坏。
漏洞代码示例
复制
class C{
Data *data;
public:
C(){ data = new Data[2];}
~C(){ delete data;}
};
在此示例中,构造函数使用数组版本的运算符 new,析构函数使用标量 delete。即使构造函数中分配的所有内存都将在析构函数中释放,也只会调用 Data 的一个析构函数。在本例中,对于使用一种机制 (new) 分配并使用另一种机制 (delete) 释放的内存,CL.FMM 已找到一个典型示例。
修正代码示例
复制
#include <iostream>
using namespace std;
class Data{
public:
Data(){ cout << "Constructing Data at " << (void *)this << endl;}
~Data() {cout << "Destroying Data at " << (void *)this << endl;}
};
//...
int main(){
C c;
return 1;
}
Output: Constructing Data at 0x602018 Constructing Data at 0x602019 Destroying Data at 0x602019
此外,new/delete 的某些实现可能导致运行时错误。要解决此问题,请使用以下释放对象的相应方法:
复制
class C{
//...
~C(){ delete[] data;}
//...
};
相关检查器
扩展
此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 C/C++ 分析。