C++因能手动分配内存空间而变得更灵活,同时也因此让出现了让大部分开发人员如坐针毡的问题——内存泄露。在Windows系统开发中,针对c++的这类工具较少,专业商业工具价格过于昂贵,是普通开发者和小型公司无法承受,因此一块可靠且开源的内存检测工具就弥足珍贵。在这里介绍一款我平时用的开源软件——Dr.Memory。
简介(简单的翻译了一下软件主页的简介)[1]
Dr.Memory是一款内存监控工具,能用于识别诸如使用未初始化的内存区域、使用非法内存区域(囊括可分配堆以外的空间、堆的上溢以及堆的下溢)、使用已释放内存区域、多次释放相同内存空间、内存泄露、句柄泄露以及GDI API的错误使用、和访问非保留线程本地存储槽等编程中产生的内存问题。
Dr.Memory在不修改原程序的情况下,可用于外部监测运行在Windows、Linux以及Mac,甚至是商业平台IA-32、AMD64和ARM上的Android。
Dr.Memory是创建在动态仪器工具平台DynamorRIO上的。
Windows命令行中简易使用方法
在确保Dr.Memory放进系统环境中,直接在命令行中输入
dr.memory [选项] 你的程序(需加绝对路径)
按回车,软件便会启动监控你的程序,直到程序退出。退出时,会自动弹出记事本,上面记录了运行结果,依据这份结果报告,可以查找到程序中的内存错误,如果你的IDE(如Visual Studio)生成了编译信息文件(pdb),并在程序的运行目录下,报告中会显示内存错误所对应的代码以及行号,然后按图索骥,将问题一一化解。
错误类型简介
理解了内存报告中,指出的内存错误是什么意思,能有助于开发者快速解决问题,下面讲些常见的错误。
- Uninitialized Read
访问未初始化的内存空间,这类问题会产生一些未知的问题,如下面这个代码,会触发上述这个问题。
/** @brief: [Error] Uninitialized Read
*/
int *arr = new int[10];
int p[10];
memcpy(p, arr, 10);
- Unaddressable Access
访问了非法内存区域,对没有申请的内存空间进行访问操作,如下代码所示。
/** @brief: [Error]Unaddressable Access
*/
int *arr = new int[10];
int num = *(arr+10);
- Invalid Heap Argument
这类错误有两种,一种是在堆上申请空间与释放的时候不相符,如代码case1所示,new数组,但是释放仅释放了指针,而不是整个数组空间;另一种是释放与新建不是同一个指针,如case2所示
/** @brief: [Error]Invalid Heap Argument
*/
Case 1:
int *arr = new int[10];
if(arr != NULL)
{
delete arr;
arr = NULL;
}
///////////////////////////////
Case 2:
int* a()
{
int *a = new int[10];
}
void b()
{
int *b = a();
if(b != NULL)
{
delete[] b;
b = NULL;
}
}
- Memory Leak
内存泄露,常见的是为变量在堆上申请空间,在其的生命周期结束时,未手动释放。
int *arr = new int[10];
for(int i=0; i<10; i++)
{
arr[i] = i;
}
下载地址以及其他
下载地址:https://github.com/DynamoRIO/drmemory/wiki/Downloads
需要说明的是,Windows版本Dr.Memory暂不支持对64位程序的内存监控,其他的版本均可以。
参考资料 【1】 [Dr.Memory主页]: http://drmemory.org/home.html