Issue 1:
opencv/modules/core/include/opencv2/core/private.hpp

Line 119
in
c3e8a82

#define CV_MALLOC_ALIGN 64

there is a problem: if a small struct which is created by new is stored with cv::Mat, the memory increases a lot, if CV_MALLOC_ALIGN = 64, else it is normal when CV_MALLOC_ALIGN=8

#include <thread>
#include <boost/circular_buffer.hpp>
#include <Eigen/Eigen>
#include <opencv2/core/core.hpp>
#include <stdlib.h>
#include <iostream>

struct OdometryEigen
{
Eigen::Matrix<double, 6, 6> p_cov;
Eigen::Matrix<double, 6, 6> v_cov;
Eigen::Matrix<double, 3, 3> R;
Eigen::Matrix<double, 3, 1> t;
Eigen::Matrix<double, 6, 1> v;
};

struct Impl
uint32_t s;
uint32_t ns;
};

struct TimestampOut
{
TimestampOut()
: impl_(new Impl)
{
}
std::shared_ptr<Impl> impl_;
};

#define ALIGN_BYTE 8

struct AlignedMat // opencv mat alloc
{
AlignedMat()
: data_(NULL)
{
}

AlignedMat(int size)
: size_(size)
, data_(NULL)
{
init();
}

AlignedMat(const AlignedMat& in)
{
size_ = in.size_;
init();
}

bool init()
{
int ret;
std::cerr << "size ----" << size_ << std::endl;
ret = posix_memalign((void**)&data_, ALIGN_BYTE, size_);

if (ret)
{
std::cerr << "failde ------------" << std::endl;
data_ = NULL;
return false;
}
std::cerr << "sucess -------" << std::endl;
for (int i = 0; i < size_; i++)
{
data_[i] = 0;
}

return true;
}

~AlignedMat()
{
if (data_)
{
free(data_);
}
}

void operator=(const AlignedMat& in)
{
if (data_)
{
free(data_);
}

size_ = in.size_;

init();
}

int size_;
char* data_;
};

#define USE_ALIGNED 1
#define USE_IMPL 0

struct ImageMat
{
#if USE_ALIGNED
ImageMat(int size)
: mat(size)
{
}

AlignedMat mat;
#else
cv::Mat mat;
#endif

ImageMat()
{
}

#if USE_IMPL
Impl timestamp;
#else
TimestampOut timestamp;
#endif
};

void addImage();
void addOdometry();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
(void) argc;
(void) argv;
std::shared_ptr<std::thread> add_thread = std::make_shared<std::thread>(&addImage);
add_thread->detach();

// add odo
addOdometry();

return 0;
}

void addImage()
{
static uint64_t i = 0u;
boost::circular_buffer<ImageMat> img_buffer(100);
uint64_t num = 1e7;
float delta_t = 1e-3;
(void) delta_t;

for(; i < num; i++)
{
// prepare data
const uint16_t width = 1920u;
const uint16_t height = 1080;
const uint64_t buffer_size = static_cast<uint64_t>(width) * height * 3u;
uint8_t buffer_stack[buffer_size];
(void) buffer_stack;
uint8_t* buffer = new uint8_t[buffer_size];

// set image data
#if USE_ALIGNED
ImageMat image(buffer_size);
#else
ImageMat image;
image.mat.create(width, height, CV_8UC3);
if (image.mat.isContinuous())
{
std::cerr << "true" << std::endl;
}
else
{
std::cerr << "flase" << std::endl;
}

for(int i = 0;i < (int)buffer_size; i++)
{
image.mat.data[i] = 0;
}
//memcpy(image.mat.data, buffer_stack, buffer_size);
memcpy(image.mat.data, buffer, buffer_size);
#endif
delete [] buffer;
usleep(1e5);
std::cerr << i << "th run \n";
img_buffer.push_back(image);

std::cerr << "image buffer size: " << img_buffer.size() << std::endl;
}

return;
}
void addOdometry()
{
static uint64_t i = 0u;
boost::circular_buffer<OdometryEigen> odo_buffer(1000);

uint64_t num = 1e7;
float delta_t = 1e-3;
(void) delta_t;

for(; i < num; i++)
{

OdometryEigen odo;
usleep(1e5);
std::cerr << i << "th odo run \n";
odo_buffer.push_back(odo);
std::cerr << "odo buffer size: " << odo_buffer.size() << std::endl;
}

return;
}

thanks.

Issue 2:
System information (version)

OpenCV => 4.1.1

Operating System / Platform => Ubuntu 18.04

Compiler => GCC 7.4.0

Detailed description

When creating large Mat objects followed by smaller allocations that are kept in a loop, resident memory keeps growing. This does not occur when the matrices are smaller or an allocation does not happen in between. If left to keep growing, the system will run out of memory and lock up, even though no more than 2000 small strings and 2 matrices should be in memory.

I've tried with OpenCV 3.4 as well, and the same thing happens

Steps to reproduce

compile the following, run it and keep an eye on memory.

#include <thread>
#include <utility>
#include <vector>
#include <opencv2/core/mat.hpp>

int main() {

// minimum size for leak on my machine: 558995 x 1
cv::Size size(600000, 5);
cv::Mat tmp(size, CV_8UC3, cv::Scalar(0, 0, 0));

std::vector<std::string> strings;

for (size_t i = 0; i < 2000; ++i)
{
cv::Mat tmp2(size, CV_8UC3, cv::Scalar(0, 0, 0));
tmp = tmp2;

// needs to be suitably large, so it gets allocated on the heap
std::string val("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
strings.push_back(val);

// gives you time to kill the process before it runs out of memory
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}

update:

this appears to be an issue with the usage of posix_memalign: if I remove the checks for it in the CMakeLists.txt and remove the checks for it then recompile, the leak disappears. Strangely, just allocating with posix_memalign instead of using cv::Mat does not create the issue on its own, there seems to be some interaction with the other operations cv::Mat does when creating it.