我正在使用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
指针并使用Mat
动态分配new
。我修改了我的代码以改为使用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);
}
答案 0 :(得分:1)
这似乎是共享指针的一个很好的用例。智能指针背后的基本思想是它的行为类似于引用计数的常规指针。当没有别的东西可以引用它时,它会自动释放自己。
您在示例中使用它们的方式是
std::vector<std::shared_ptr<Mat> > images;
std::shared_ptr<Mat> mat_ptr (new Mat(height, width, CV_8UC3));
images.push_back(mat_ptr);
Here是一个方便的教程,有关共享指针的更多信息。如果我误解了您的问题/问题,请随时跟进。
答案 1 :(得分:1)
如果您小心实际删除对象,则没有内存泄漏。话虽这么说,有一些方法可以在不太容易出现人为错误的向量中存储指针(即你忘记在应用程序的某些角落删除对象)。
如果您可以使用C ++ 11,那么我建议使用std::shared_ptr
而不是原始指针。这将确保在不再使用Mat
对象的任何代码时(自动)删除内存。
还有一个优点,除了必须更改指针的类型之外,您不需要进行任何其他修改。通常的ptr->member
和*ptr
表达式也适用于std::shared_ptr
。
这里有一些documentation on std::shared_ptr
。此外,根据您的具体需求,您可能还需要查看std::reference_wrapper
。
编辑:由于C ++ 11不是一个选项,您可以尝试boost::shared_ptr
- 标准std::shared_ptr
基于Boost。如果Boost也不是一个选项,你可以实现自己的共享指针,这不是很难。
您的计划规模是值得考虑的事情。如果您的应用程序相当小,并且您几乎没有机会忘记可能导致内存泄漏的一些极端情况,那么所有这些都可能过度工程化。如果只是“手动”删除对象,则会考虑这样做。