I’m using OpenCV 4.11.0 and Ubuntu 22.04.5.
#include <vector>
#include <thread>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/utility.hpp>
int main(int argc, char** argv)
{
std::vector<std::thread> threads(1); // can be increased up to 4 to leak more memory. Beyond that it doesn't leak more
for (std::uint32_t i = 0; i < threads.size(); ++i)
{
threads[i] = std::thread([] { std::this_thread::sleep_for(std::chrono::seconds(1)); });
}
for (std::int32_t i = threads.size() - 1; i >= 0; --i)
{
threads[i].join();
}
cv::Mat mat(1024, 1024, CV_8UC1);
cv::Mat down(512, 512, CV_8UC1);
cv::pyrDown(mat, down);
}
The above program produces the following leaks (more leaks if more threads are used):
==2155== Memcheck, a memory error detector
==2155== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2155== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==2155== Command: ./a.out
==2155==
==2155==
==2155== HEAP SUMMARY:
==2155== in use at exit: 17,476 bytes in 146 blocks
==2155== total heap usage: 1,306 allocs, 1,160 frees, 1,756,269 bytes allocated
==2155==
==2155== 288 bytes in 1 blocks are possibly lost in loss record 32 of 39
==2155== at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2155== by 0x40147D9: calloc (rtld-malloc.h:44)
==2155== by 0x40147D9: allocate_dtv (dl-tls.c:375)
==2155== by 0x40147D9: _dl_allocate_tls (dl-tls.c:634)
==2155== by 0x73B17B4: allocate_stack (allocatestack.c:430)
==2155== by 0x73B17B4: pthread_create@@GLIBC_2.34 (pthread_create.c:647)
==2155== by 0x71AA328: std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30)
==2155== by 0x109700: std::thread::thread<main::{lambda()#1}, , void>(main::{lambda()#1}&&) (in /home/vchidambaram/junk/opencv_leak_test/a.out)
==2155== by 0x10942B: main (in /home/vchidambaram/junk/opencv_leak_test/a.out)
==2155==
==2155== 5,184 bytes in 18 blocks are possibly lost in loss record 39 of 39
==2155== at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2155== by 0x40147D9: calloc (rtld-malloc.h:44)
==2155== by 0x40147D9: allocate_dtv (dl-tls.c:375)
==2155== by 0x40147D9: _dl_allocate_tls (dl-tls.c:634)
==2155== by 0x73B17B4: allocate_stack (allocatestack.c:430)
==2155== by 0x73B17B4: pthread_create@@GLIBC_2.34 (pthread_create.c:647)
==2155== by 0x4B03E24: cv::WorkerThread::WorkerThread(cv::ThreadPool&, unsigned int) (in /usr/local/lib/libopencv_core.so.4.11.0)
==2155== by 0x4B05A01: cv::ThreadPool::reconfigure_(unsigned int) (in /usr/local/lib/libopencv_core.so.4.11.0)
==2155== by 0x4B063EC: cv::ThreadPool::run(cv::Range const&, cv::ParallelLoopBody const&, double) (in /usr/local/lib/libopencv_core.so.4.11.0)
==2155== by 0x4AF012B: cv::parallel_for_(cv::Range const&, cv::ParallelLoopBody const&, double) (in /usr/local/lib/libopencv_core.so.4.11.0)
==2155== by 0x58DFBA0: void cv::pyrDown_<cv::FixPtCast<unsigned char, 8> >(cv::Mat const&, cv::Mat&, int) (in /usr/local/lib/libopencv_imgproc.so.4.11.0)
==2155== by 0x58ED10D: cv::pyrDown(cv::_InputArray const&, cv::_OutputArray const&, cv::Size_<int> const&, int) (in /usr/local/lib/libopencv_imgproc.so.4.11.0)
==2155== by 0x109573: main (in /home/vchidambaram/junk/opencv_leak_test/a.out)
==2155==
==2155== LEAK SUMMARY:
==2155== definitely lost: 0 bytes in 0 blocks
==2155== indirectly lost: 0 bytes in 0 blocks
==2155== possibly lost: 5,472 bytes in 19 blocks
==2155== still reachable: 12,004 bytes in 127 blocks
==2155== suppressed: 0 bytes in 0 blocks
==2155== Reachable blocks (those to which a pointer was found) are not shown.
==2155== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==2155==
==2155== For lists of detected and suppressed errors, rerun with: -s
==2155== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
I’m not terribly concerned with the second leak, since I don’t expect the thread pool to be cleaned up when it exits, but the first one is weird to me. Does anyone know why valgrind thinks stuff is leaked on the threads that are joined before I even use OpenCV? Since it never leaks more than 4 blocks even with more than 4 threads, I don’t think it’s necessarily an error, but I still don’t understand why it’s happening. Unfortunately, I can’t suppress the errors either, because the stack trace for the leak is identical to a thread that doesn’t get joined, and I don’t want to miss those if they happen.