【发布时间】:2013-11-01 20:39:23
【问题描述】:
我正在使用 OpenCV,我想在一个向量中存储许多图像(Mat 对象)。我已将向量声明如下以存储指向Mat 对象的指针。
std::vector<Mat*> images;
Mat 对象是使用 new 关键字创建的,然后添加到向量中。
Mat *img = new Mat(height, width, CV_8UC3);
// set the values for the pixels here
images.push_back(img);
如何确保释放Mat 对象占用的内存以避免内存泄漏?
我现在正在做的事情如下:
Mat *im = images.at(index);
// process and display image here
delete(im);
Valgrind 正在报告可能的内存泄漏,参考创建的 Mat 对象。我错过了什么吗?
编辑:
好的。显然最好避免使用Mat 指针并使用new 动态分配Mat。我已修改我的代码以使用 std::vector<Mat> 代替。但是,我仍然看到一些由Mat 分配的块可能在 Valgrind 报告中丢失了。我还注意到程序运行时内存使用量稳步增加。
让我澄清一下我在做什么。我在函数中创建图像并将它们放在缓冲区中(内部使用std::deque)。这个缓冲区然后被另一个函数访问以检索和图像并将其传递给另一个执行处理和渲染的函数。
class Render {
public:
void setImage(Mat& img) {
this->image = img;
}
void render() {
// process image and render here
}
private:
Mat image;
}
不断从缓冲区获取图像并渲染它们的线程。
void* process(void *opaque) {
ImageProcessor *imgProc = (ImageProcessor*) opaque;
Mat img;
while (imgProc->isRunning) {
// get an image from the buffer
imgProc->buffer->getFront(img);
// set the image
imgProc->renderer->setImage(img);
// process and render
imgProc->renderer->render();
}
}
现在,所有内容都作为对象引用传递(即Mat&)。我假设从缓冲区获取图像并将其传递给渲染函数后,对该对象的唯一引用将在该函数中。因此,当我得到另一个图像时,将不再有对该对象的引用,它将被销毁。但是 Valgrind 给了我以下信息:
25,952,564 bytes in 11 blocks are possibly lost in loss record 14,852 of 14,853
in ImageProcessor::generateImage() in ImageProcessor.cpp:393
1: malloc in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
2: cv::fastMalloc(unsigned long) in /usr/local/lib/libopencv_core.so.2.4.2
3: cv::Mat::create(int, int const*, int) in /usr/local/lib/libopencv_core.so.2.4.2
4: cv::Mat::create(int, int, int) in /usr/local/include/opencv2/core/mat.hpp:353
5: cv::Mat::Mat(int, int, int) in /usr/local/include/opencv2/core/mat.hpp:75
...
这里是generateImage():
void generateImage() {
Mat img(h, w, CV_8UC3);
// set values of pixels here
this->buffer->pushBack(img);
}
【问题讨论】:
-
Mat 类管理内存分配并具有引用计数,因此
std::vector<Mat>为您完成工作,并且仍然只复制指针和大小信息,而没有不必要的分配和大型 Matrix 内容的副本。跨度> -
@mars 在按照您的建议更新问题后,我已经用代码的某些部分更新了问题。虽然我仍然遇到内存泄漏,但问题仍然存在。
-
这里显示的代码部分应该可以工作。你能详细说明一下那个不透明的指针吗?它来自哪里,它是如何被初始化的,谁拥有它并在不再需要它时调用
ImageProcessor的析构函数?注意void * opaque=new ImageProcessor; do_stuff(opaque); free opaque;调用ImageProcessor的构造函数,但调用void的析构函数。 -
@mars 不透明指针基本上是指向
ImageProcessor对象的指针。正如我提到的process()是一个线程函数。我使用 pthreads 库创建了一个线程,并传递了一个指向process()的指针和一个指向基本上是线程函数参数的对象的指针。这就是使用pthread_create()创建线程的方式。在这里,我只是传递了一个对ImageProcessor的引用,以便线程可以调用它的方法。何时何地调用ImageProcessor的析构函数应该不是问题。因为我要从缓冲区中删除Mat对象。
标签: c++ opencv memory-leaks