6

when I try to create a cv::Mat and release it afterwards (code below), I still have (according to valgrind) a memory leak by about 1 Byte per Pixel.

Does anyone know how to free the memory of an cv::Mat properly?

Thanks for ansers :)

Code:

int main(int argc, char** argv)
{
  cv::Mat* matrx = new cv::Mat(1000,1000,CV_8UC1,0.);
  matrx->release();
  delete matrx;
  return 0;
}

Valgrind:

[...]
==29420==    1,000,028 bytes in 1 blocks are definitely lost in loss record 372 of 372
==29420==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29420==    by 0x5438877: cv::fastMalloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libopencv_core.so.2.4.8)
==29420==    by 0x536FE2A: cv::Mat::create(int, int const*, int) (in /usr/lib/x86_64-linux-gnu/libopencv_core.so.2.4.8)
==29420==    by 0x426FB5: cv::Mat::create(int, int, int) (mat.inl.hpp:663)
==29420==    by 0x426ECD: cv::Mat::Mat(int, int, int, cv::Scalar_<double> const&) (mat.inl.hpp:347)
==29420==    by 0x425A09: main (main.cpp:18)
==29420== 
==29420== LEAK SUMMARY:
==29420==    definitely lost: 1,000,028 bytes in 1 blocks
==29420==    indirectly lost: 0 bytes in 0 blocks
==29420==      possibly lost: 5,072 bytes in 95 blocks
==29420==    still reachable: 304,758 bytes in 1,348 blocks
==29420==         suppressed: 0 bytes in 0 blocks
[...]
cagcoach
  • 625
  • 7
  • 24
  • 2
    It's usually a bad idea to use pointers to `Mat` objects because of internal reference counting. Just put them on the stack: `int main(){Mat a(10,10,CV_8UC1); return 0;}` – Miki Sep 05 '16 at 14:23
  • @Miki I just reduced my code to make the question easier and find the issue. I need the Matrix in different classes so need a pointer. Even std::shared_ptr didn't solved the problem – cagcoach Sep 05 '16 at 14:30
  • So have one class own it as a non-pointer, and give the rest of the classes a pointer/reference. – Ivan Rubinson Sep 05 '16 at 14:36
  • According to the documentation cv::Mat dtor calls release so I think your call to release is redundant, what happens if you only call delete on the pointer? – Jonathan Sep 05 '16 at 14:59
  • @Jonathan same problem even without `release()` – cagcoach Sep 05 '16 at 15:32
  • I just ran this program with OpenCV 2.4.12 and got no issue with valgrind. The release call is somewhat redundant. Can you post more information (e.g., on how you compiled and linked the above, what headers you included) in case this is a problem with the particular build of OpenCV? – Robert Prévost Sep 05 '16 at 15:35
  • @RobertPrévost I actually use OpenCV 3.1.0-dev. the only include is `#include ` – cagcoach Sep 05 '16 at 15:42
  • 1
    After downgrading to OpenCV 2.4.8 the problem was gone. I reported an issue on GitHub. https://github.com/opencv/opencv/issues/7238 – cagcoach Sep 05 '16 at 17:08
  • 4
    I suggested 2.4.8 because the trace in the valgrind output lists a SO from 2.4.8. This might be the root cause. You compiled for 3.1, but the runtime that was used was 2.4.8. – Robert Prévost Sep 05 '16 at 19:31

2 Answers2

4

The feedback from opencv github seems clear: you compiled with OpenCV 3.x but use OpenCV 2.4.8 at runtime. Since they are not binary compatible, it does not free properly the cv::Mat. Let export your LD_LIBRARY_PATH to the OCV_DIST/lib of OpenCV 3.x used to compile.

Note that if you delete the pointer you don't even need to release() before.

xiawi
  • 1,772
  • 4
  • 19
  • 21
1

Quoted the following from the documentation page: (http://docs.opencv.org/2.4.9/modules/core/doc/basic_structures.html#mat-release):

void Mat::release() The method decrements the reference counter associated with the matrix data. When the reference counter reaches 0, the matrix data is deallocated and the data and the reference counter pointers are set to NULL’s.

The above means that when you do "delete matrx;" you are trying to delete a memory zone that already points to NULL, which generates a run-time error.