释放 cv::Mat 而不释放内存

发布于 2024-12-09 06:32:17 字数 168 浏览 0 评论 0原文

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

我知道这种情况会发生在从外部数据创建的 cv::Mat 上,我只需要将此功能用于一般的 cv::Mat 即可。

有办法做到这一点吗?

I pass the Mat data (not a cv::Mat object) to a function, And make this function the new owner of this data. however, I need a method to free the original object, without freeing the data buffer it points to.

I know that this will happen to cv::Mat that were created from external data, I just need to use this feature for general cv::Mat.

Is there a way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小矜持 2024-12-16 06:32:17

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

实际上,将数据与 Mat 分离并不是一个好主意:

  • 它不是为此而设计的;
  • 你不能保证从一般的cv::Mat获得的指针指向分配的内存块的开头;
  • 您很可能无法自己释放该内存,因为 cv::Mat 可能使用自己的内存分配例程(有很多原因需要这样做,例如对齐)。
  • 即使你找到了解决数据指针所有问题的方法,你仍然无法避免Mat引用计数器的内存泄漏。

因此,Mat 只能保证支持两种方式:

  • 提供有关 Mat 创建的指针;
  • 将数据复制到缓冲区。

任何其他方式即使在当前版本中有效,也可能在未来版本中被破坏。

You can use addref() method but you will have a memory leak.

Actually it is not a good idea to detach data from Mat:

  • It was not designed for that;
  • You can not guarantee that pointer obtained from general cv::Mat points to the beginning of allocated memory block;
  • Most probably you will be unable to release that memory by yourself because cv::Mat may use own memory allocation routines (there are a lot of reasons to do that, for example alignment).
  • Even if you find a way to solve all the problems with data pointer, you still can not avoid memory leak for Mat reference counter.

So there are only two ways that Mat is guaranteed to support:

  • Provide your pointer on Mat creation;
  • Copy data to you buffer.

Any other way can be broken in future versions even if it works in current.

本宫微胖 2024-12-16 06:32:17

您可以使用 lambda 捕获 Mat,并且可以使用该 lambda 作为删除器来延长其生命周期并将其绑定到 shared_ptr/unique_ptr。

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

当您不想在公共接口上使用 opencv,并且无法提供有关 Mat 创建的指针或不想将数据复制到缓冲区时,它非常有用。

You can capture the Mat with a lambda, and you can use this lambda as a deleter to extend and bound its life to a shared_ptr/unique_ptr.

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

Its useful when you don't want to use the opencv on your public interface, and you can't provide your pointer on Mat creation or don't want to copy data to your buffer.

夏末的微笑 2024-12-16 06:32:17

使用 release()

Ptr

http://opencv.willowgarage.com /documentation/cpp/basic_structs.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> 类是一个包装相应类型指针的模板类。它类似于shared_ptr,它是Boost库的一部分(http: //www.boost.org/doc/libs/1_40_0/libs/smart_ptr/shared_ptr.htm )以及一部分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; 。但是,如果以不同方式释放对象,则应创建专门的方法。例如,如果你想包装 FILE ,delete_obj 可以实现如下:

template<>内联 void Ptr::delete_obj()
{
fclose(obj); // 之后不需要清除指针,
// 这是在外部完成的。
}
...

// 现在使用它:
Ptr f(fopen("myfile.txt", "r"));
if(f.empty())
扔 ...;
fprintf(f, ....);
...
// 文件将被 Ptr 析构函数自动关闭。

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

USE release()

Ptr

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

A template class for smart reference-counting pointers

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;
};

The class Ptr<_Tp> is a template class that wraps pointers of the corresponding type. It is similar to shared_ptr that is a part of Boost library ( http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/shared_ptr.htm ) and also a part of the C++0x standard.

By using this class you can get the following capabilities:

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.

The class Ptr treats the wrapped object as a black box, the reference counter is allocated and managed separately. The only thing the pointer class needs to know about the object is how to deallocate it. This knowledge is incapsulated in Ptr::delete_obj() method, which is called when the reference counter becomes 0. If the object is a C++ class instance, no additional coding is needed, because the default implementation of this method calls delete obj; . However, if the object is deallocated in a different way, then the specialized method should be created. For example, if you want to wrap FILE , the delete_obj may be implemented as following:

template<> inline void Ptr::delete_obj()
{
fclose(obj); // no need to clear the pointer afterwards,
// it is done externally.
}
...

// now use it:
Ptr f(fopen("myfile.txt", "r"));
if(f.empty())
throw ...;
fprintf(f, ....);
...
// the file will be closed automatically by the Ptr destructor.

Note : The reference increment/decrement operations are implemented as atomic operations, and therefore it is normally safe to use the classes in multi-threaded applications. The same is true for Mat and other C++ OpenCV classes that operate on the reference counters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文