面试题答案
一键面试基本步骤
- 包含头文件:在代码开头包含
afx.h
,因为CMemoryState
是 MFC 库中的类。
#include <afx.h>
- 创建
CMemoryState
对象:在程序的关键位置,通常是在需要检测内存泄漏的代码段前后分别创建CMemoryState
对象。
CMemoryState state1, state2, stateDiff;
- 获取初始内存状态:在要检测的代码段执行前,调用
state1.Checkpoint()
获取初始内存状态。
state1.Checkpoint();
- 执行可能导致内存泄漏的代码:这里放置包含动态内存分配和释放操作的代码。
- 获取结束内存状态:在上述代码段执行后,调用
state2.Checkpoint()
获取结束时的内存状态。
state2.Checkpoint();
- 比较内存状态:调用
stateDiff.Difference(state1, state2)
比较初始和结束状态,得到差异状态。
stateDiff.Difference(state1, state2);
- 报告内存泄漏:如果存在差异,调用
stateDiff.DumpStatistics()
输出内存泄漏的统计信息。
if (stateDiff.IsDifference()) {
stateDiff.DumpStatistics();
}
原理
CMemoryState
类通过记录程序在不同时间点的内存分配情况来检测内存泄漏。Checkpoint
方法会记录当前堆内存的状态,包括已分配内存块的数量、类型和大小等信息。Difference
方法通过比较两个 CMemoryState
对象记录的状态,找出在两个时间点之间没有正确释放的内存块,即内存泄漏。
简单类中检测内存泄漏示例
假设有如下简单类:
class MyClass {
public:
MyClass() {
data = new int[10];
}
~MyClass() {
// 假设这里忘记释放内存
// delete[] data;
}
private:
int* data;
};
在使用这个类的代码中检测内存泄漏:
int main() {
CMemoryState state1, state2, stateDiff;
state1.Checkpoint();
MyClass obj;
state2.Checkpoint();
stateDiff.Difference(state1, state2);
if (stateDiff.IsDifference()) {
stateDiff.DumpStatistics();
}
return 0;
}
在上述代码中,MyClass
类的构造函数分配了动态内存,但析构函数没有释放它。通过 CMemoryState
工具在创建和销毁 MyClass
对象前后记录内存状态并比较,就可以检测到内存泄漏。如果析构函数正确释放内存(即取消注释 delete[] data;
),则不会检测到内存泄漏。