2011-10-09 106 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的您的公共接口上,你不能提供您的指針放在墊創建或不想將數據複製到緩衝區。