OpenCV2.0中OpenCV源码中的安全指针和指针对齐

转自:http://hi.baidu.com/maxint/blog/item/fc817c2f29881f331e3089ef.html

OpenCV2.0中为很多1.0中 C 语言的数据结构提供了 C++ 的类了,考虑到兼容性,保留旧的API。但是凭借C++构造和析造的功能,OpenCV2.0的内存管理方便了许多,使用新API的代码中类似 cvRelease*** 的代码将不复存在。同时CV2.0也提供了一个安全指针类,让旧的需要手动管理内存的数据结构(如IplImag, CvMat等)也可以不用手动 Release 了,快哉!不过推荐直接用新的API(一些是仿Matlab的),如Mat,程序可以更简洁、更直观。一个精典的OpenCV的Hello World程序现在可以这样写:

#include 
#include

using namespace cv;

#ifdef _DEBUG
#pragma comment(lib, "cv200d.lib")
#pragma comment(lib, "cxcore200d.lib")
#pragma comment(lib, "highgui200d.lib")
#else
#pragma comment(lib, "cv200.lib")
#pragma comment(lib, "cxcore200.lib")
#pragma comment(lib, "highgui200.lib")
#endif // _DEBUG

const string WIN_NAME = "Lena";

int main(int argc, char* argv[])
{
Mat img = imread("lena.jpg");
namedWindow(WIN_NAME, CV_WINDOW_AUTOSIZE);
imshow(WIN_NAME, img);
waitKey(0);

return 0;
}

安全指针

如果你还是习惯用CV1.0的API,那一定要试试CV2.0的安全指针(也叫智能指针)Ptr template。据说这个是参考了C++0x和 Boost库的相关技术。使用也很简单:
Ptr img = cvReadImage("lena.jpg"); // 不用cvReleaseImage();
无聊的我把Ptr类从 OpenCV 中独立出来,template class 定义如下:

template class Ptr
{
public:
Ptr();
Ptr(_Tp* _obj);
~Ptr();
Ptr(const Ptr& ptr);
Ptr& operator = (const Ptr& ptr);
void addref();
void release();
void delete_obj();
bool empty() const;

_Tp* operator -> ();
const _Tp* operator -> () const;

operator _Tp* ();
operator const _Tp*() const;
protected:
_Tp* obj;
int* refcount;
};
简单地说,就是加了个指针引用数(refcount)和一些方便调用的操作符重装(operator ->;())。值得注意的是,Ptr template 对指针指向的对象有一个要求,就是可以用 delete 操作土符来释放内存。你可能就想到 IplImage 就不满足这个要求了,这怎么办?可以使用模板特化(template specialization)重载 Ptr::delete_obj() 函数:
template<> inline void Ptr::delete_obj()
{ cvReleaseImage(&obj); }
PS:考虑到多线程时,CV2.0中的一些基本操作(如加法运算CV_ADD)都写成了函数或宏,保证互斥资源访问安全,看源代码时可注意下。

指针对齐

指针对齐也可以叫作内存地址对齐,主要是考虑到在一些架构上,只有被指定数(如4)整除的内存地址才可以正常访问,否则程序就会Crash了。CV2.0中的很多指针都是“对齐”过的,如指针的地址都是可以被16整除。CV2.0的内存主要是通过 malloc 来分配的,返回的内存地址不可能都可以被16整除,所以要进行对齐操作。那如何对齐,对齐后截断后剩下来的内存怎么维护?

CV2.0的这样维护的:在 malloc 是多申请一个指针的空间,这个指针指向 malloc 得到的真实内存地址,只在 free 时使用它。相关函数有

typedef unsigned char uchar;
#define CV_MALLOC_ALIGN 16
//

template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp))
{
return (_Tp*)(((size_t)ptr + n-1) & -n);
}

__declspec(dllexport) void* fastMalloc( size_t size )
{
uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
^- HERE 多申请一个 void* 的空间,
用于存储 udata
uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN);
adata[-1] = udata; <- 存储 udata
return adata;
}

__declspec(dllexport) void fastFree(void* ptr)
{
if(ptr)
{
uchar* udata = ((uchar**)ptr)[-1];
assert(udata < (uchar*)ptr &&
((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+CV_MALLOC_ALIGN));
free(udata);
}
}

Reference

  1. OpenCV2.0 自带的《The Reference Manual》
  2. What is "Pointer Alignment"

你可能感兴趣的:(OpenCV2.0中OpenCV源码中的安全指针和指针对齐)