opencv中的安全指针和指针对齐 Ptr<>

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

1. 安全指针

从opencv2.0开始,很多C数据结构变成了C++的类,考虑到兼容性,保留旧的API。在内存管理方面,提供安全指针类Ptr,让在此以前旧的需要手动管理内存的数据结构(IplImage, CvMat等)无需手动Release,用法为:

Ptr<IplImage> img = cvReadImage("Lena.jpg");

Ptr是一个模板类,在opencv中定义如下:

复制代码
template<typename _Tp> 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<Iplimage>::delete_obj() 函数:

template<> inline void Ptr<IplImage>::delete_obj()
{ cvReleaseImage(&obj); }

2. 指针对齐(http://bytes.com/topic/c/answers/213142-what-pointer-alignment)

为什么要指针对齐? 这是因为在某些架构上,只有能被指定数(如4,16)整除的内存地址才能够被访问,否则程序会crash,或者出现错误的结果,或者数据的访问变慢。举个例子来说,很多系统都要求interger的地址从偶数开始。opencv2.0以上版本很多指针都是被对齐过的,使指针地址能够被16整除。opencv中的内存一般是通过malloc分配,不能保证都是都能被16整除,此时需要截断,但是剩下的内存要如何维护? CV2.0的这样维护的:在 malloc 是多申请一个指针的空间,这个指针指向 malloc 得到的真实内存地址,只在 free 时使用它。相关函数:

复制代码
typedef unsigned char uchar;
#define CV_MALLOC_ALIGN 16
template<typename _Tp> 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);  
    }
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值