上文介绍了C/C++编码中内存泄露的问题,不过经过本人测试,好像对用opencv工具包进行编码中的内存泄露并不起作用。CrtSetDbgFlag函数应该针对new/malloc这种方式分配内存的,而opencv的很多函数把内存分配封装了,直接返回一个指针(e.g. cvCreateImage返回IplImage指针),因而并不能检测出opencv编码的内存泄露.(这一段不知道说得对不对,还有待查证:0) ).针对这个问题,网上有一个比较好的解决方法,就直接来过来用了。它是一个针对opencv的内存泄露检测的类,实现如下:
//头文件
#ifndef OPENCV_MEM_TRACKER_H
#define OPENCV_MEM_TRACKER_H
#include
#include
// 内存泄漏追踪类
class MemTracker
{
public:
MemTracker
(void);
~MemTracker
(void);
private:
// 登记分配/释放的内存
void regAlloc
(void *ptr,
size_t size
);
void regFree
(void *ptr
);
// 输出泄漏的内存
int output
(FILE* fp
=stderr);
private:
// 分配内存
static void* alloc_func
(size_t size,
void *userdata
);
// 释放内存
static int free_func
(void *ptr,
void *userdata
);
private:
struct Ptr
{
void *ptr;
// 内存地址
size_t size;
// 内存大小
int id;
Ptr
(void *ptr,
size_t size,
int id
)
{
this
->ptr
= ptr;
this
->size
= size;
this
->id
= id;
}
};
// 记录当前使用中的内存
std
::vector<Ptr
> m_memTracker;
// alloc_func对应的编号
int m_id;
};
#endif // OPENCV_MEM_TRACKER_H
//cpp文件
#include "MemTracker.h"
#include
#include
MemTracker
::MemTracker(void)
{
m_id
= 0;
// 注册管理函数
cvSetMemoryManager
(alloc_func, free_func,
(void*)this);
}
MemTracker
::~MemTracker
(void)
{
// 取消管理函数
cvSetMemoryManager
(NULL,
NULL,
NULL);
// 输出结果
this
->output
();
}
// 登记分配/释放的内存
void MemTracker
::regAlloc(void *ptr,
size_t size
)
{
// 每次记录一个新的m_id
m_memTracker.
push_back(Ptr
(ptr, size, m_id
++));
}
void MemTracker
::regFree(void *ptr
)
{
int i;
for(i
= 0; i
< m_memTracker.
size();
++i
)
{
// 删除记录
if(m_memTracker
[i
].
ptr == ptr
)
{
m_memTracker
[i
] = m_memTracker
[m_memTracker.
size()-1];
m_memTracker.
pop_back();
return;
}
}
}
// 输出泄漏的内存
int MemTracker
::output(FILE* fp
)
{
int n
= m_memTracker.
size();
int i;
for(i
= 0; i
< n;
++i
)
{
fprintf(fp,
"%d: %p, %u\n", m_memTracker
[i
].
id, m_memTracker
[i
].
ptr, m_memTracker
[i
].
size);
}
return n;
}
// 分配内存
void* MemTracker
::alloc_func(size_t size,
void *userdata
)
{
assert(size
> 0 && userdata
!= NULL);
// 分配内存
void *ptr
= malloc(size
);
if(!ptr
) return NULL;
// 登记
MemTracker
*tracker
= (MemTracker
*)userdata;
tracker
->regAlloc
(ptr, size
);
//
return ptr;
}
// 释放内存
int MemTracker
::free_func(void *ptr,
void *userdata
)
{
assert(ptr
!= NULL && userdata
!= NULL);
// 释放内存
free(ptr
);
// 登记
MemTracker
*tracker
= (MemTracker
*)userdata;
tracker
->regFree
(ptr
);
// CV_OK == 0
return 0;
}
//测试程序
int main
()
{
//实例化
MemTracker tracker;
//加载图片,注意它没有被release掉
IplImage
* pImg
= cvLoadImage
("E:\\test photos3\\SDC10126.JPG",
1);
return 0;
}
使用的时候,MemTracker会跟每一个指针分配一个id,并记录它的分配与释放情况,对没有释放的内存将会被打印出来,包括此指针的id号, 指针的16进制值,以及所指内存的大小。按f5进行调试,根据id号找到泄露内存代码的具体位置,添加释放代码。