2011-10-09 105 views
3

我将Mat数据(不是cv :: Mat对象)传递给一个函数,并使此函数成为此数据的新所有者。但是,我需要一种方法来释放原始对象,而不释放它指向的数据缓冲区。免费cv ::垫没有释放内存

我知道这将发生在从外部数据创建的cv :: Mat中,我只需要将这个特性用于常规cv :: Mat。

有没有办法做到这一点?

回答

8

您可以使用addref()方法,但是您将有内存泄漏

其实它不是从垫分离的数据是个好主意:

  • 它不是专为;
  • 你不能保证从一般cv :: Mat获得的指针指向分配的内存块的开始位置;
  • 大多数情况下,您可能无法自行释放该内存,因为cv :: Mat可能使用自己的内存分配例程(有很多原因可以做到这一点,例如对齐)。
  • 即使您找到解决数据指针所有问题的方法,仍无法避免Mat引用计数器的内存泄漏。

那么只有两种方式垫保证支持:

  • 提供您垫上创建的指针;
  • 将数据复制到您的缓冲区。

任何其他方式可以在未来的版本中打破,即使它在当前工作。

0

USE 释放()

PTR

http://opencv.willowgarage.com/documentation/cpp/basic_structures.html

模板类智能引用计数指针

template<typename _Tp> class Ptr 
{ 
public: 
    // default constructor 
    Ptr(); 
    // constructor that wraps the object pointer 
    Ptr(_Tp* _obj); 
    // destructor: calls release() 
    ~Ptr(); 
    // copy constructor; increments ptr's reference counter 
    Ptr(const Ptr& ptr); 
    // assignment operator; decrements own reference counter 
    // (with release()) and increments ptr's reference counter 
    Ptr& operator = (const Ptr& ptr); 
    // increments reference counter 
    void addref(); 
    // decrements reference counter; when it becomes 0, 
    // delete_obj() is called 
    void release(); 
    // user-specified custom object deletion operation. 
    // by default, "delete obj;" is called 
    void delete_obj(); 
    // returns true if obj == 0; 
    bool empty() const; 

    // provide access to the object fields and methods 
    _Tp* operator ->(); 
    const _Tp* operator ->() const; 

    // return the underlying object pointer; 
    // thanks to the methods, the Ptr<_Tp> can be 
    // used instead of _Tp* 
    operator _Tp*(); 
    operator const _Tp*() const; 
protected: 
    // the encapsulated object pointer 
    _Tp* obj; 
    // the associated reference counter 
    int* refcount; 
}; 

类PTR < _TP>是一个模板类包装相应类型的指针。它与Boost库(http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/shared_ptr.htm)的一部分shared_ptr类似,也是C++ 0x标准的一部分。

通过使用这个类,你可以得到以下功能:

default constructor, copy constructor and assignment operator for an arbitrary C++ class or a C structure. For some objects, like files, windows, mutexes, sockets etc, copy constructor or assignment operator are difficult to define. For some other objects, like complex classifiers in OpenCV, copy constructors are absent and not easy to implement. Finally, some of complex OpenCV and your own data structures may have been written in C. However, copy constructors and default constructors can simplify programming a lot; besides, they are often required (e.g. by STL containers). By wrapping a pointer to such a complex object TObj to Ptr<TObj> you will automatically get all of the necessary constructors and the assignment operator. 
all the above-mentioned operations running very fast, regardless of the data size, i.e. as “O(1)” operations. Indeed, while some structures, like std::vector provide a copy constructor and an assignment operator, the operations may take considerable time if the data structures are big. But if the structures are put into Ptr<> , the overhead becomes small and independent of the data size. 
automatic destruction, even for C structures. See the example below with FILE* . 
heterogeneous collections of objects. The standard STL and most other C++ and OpenCV containers can only store objects of the same type and the same size. The classical solution to store objects of different types in the same container is to store pointers to the base class base_class_t* instead, but when you loose the automatic memory management. Again, by using Ptr<base_class_t>() instead of the raw pointers, you can solve the problem. 

类PTR把被包装的对象作为一个黑盒子,引用计数器分配和单独管理。指针类需要知道的唯一对象是如何释放它。这些知识被封装在Ptr :: delete_obj()方法中,当引用计数器变为0时,该方法被调用。如果对象是C++类实例,则不需要额外的编码,因为此方法的默认实现调用delete obj; 。但是,如果以不同的方式释放对象,则应该创建专门的方法。例如,如果你想换文件时,delete_obj可以实现如下:

模板<>内嵌无效PTR :: delete_obj(){ FCLOSE (OBJ); //之后不需要清除指针, //它是在外部完成的。 } ...

//现在使用它: PTR F(的fopen( “myfile.txt的”, “R”)); if(f.empty()) throw ...;如果(f.empty()) throw ...; fprintf(f,....); ... //该文件将由Ptr析构函数自动关闭。

注意:引用递增/递减操作是作为原子操作实现的,因此在多线程应用程序中使用类通常是安全的。对于在参考计数器上运行的Mat和其他C++ OpenCV类也是如此。

+0

//递减参考计数器;当它变为0时,// delete_obj()被调用--- *在我描述的情况下调用release会删除对象,这样被调用的函数将获得释放的内存* –

3

您可以使用lambda捕获Mat,并且可以使用此lambda作为删除器来扩展和限制其生命到shared_ptr/unique_ptr。

Mat matrix; 
... 
std::shared_ptr<uchar*> ptr(matrix.ptr(),[matrix](uchar*){}); 

它有用,当你不想使用OpenCV的您的公共接口上,你不能提供您的指针放在垫创建或不想将数据复制到缓冲区。