1

我正在使用 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指针和动态分配Matusing new。我已经修改了我的代码以使用std::vector<Mat>。但是,我仍然在 Valgrind 报告中看到一些Mat可能丢失的块。我还注意到程序运行时内存使用量稳步增加。

让我澄清一下我在做什么。我在函数中创建图像并将它们放在缓冲区中(内部使用 a 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);
}
4

2 回答 2

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

是一个方便的教程,了解更多关于共享指针的信息。如果我对您的问题/问题有误解,请随时在下面跟进。

于 2013-11-01T20:46:39.220 回答
1

如果您小心地实际删除对象,则不会出现内存泄漏。话虽如此,有一些方法可以将指针存储在不易出现人为错误的向量中(即,您忘记在应用程序的某些极端情况下删除对象)。

如果您可以使用 C++11,那么我建议您使用std::shared_ptr而不是原始指针。这将确保当不再有任何代码使用您的Mat对象时(自动)删除内存。

还有一个优点是,除了必须更改指针的类型之外,您无需进行任何其他修改。通常的ptr->member*ptr表达式也适用于std::shared_ptr

这里有一些关于std::shared_ptr. 此外,根据您的具体需求,您可能还想研究一下std::reference_wrapper


编辑:由于 C++11 不是一个选项,您可以尝试boost::shared_ptr- 该标准std::shared_ptr基于 Boost 标准。如果 Boost 也不是一个选项,您可以实现自己的共享指针,这不是很难。

你的程序的大小是另外一个需要考虑的事情。如果您的应用程序相当小,并且您几乎没有机会忘记一些可能导致内存泄漏的极端情况,那么所有这些都可能是过度设计的。如果只是“手动”删除对象就可以考虑这样做。

于 2013-11-01T20:50:57.870 回答