<p dir="auto"></p><div class="Box Box--condensed my-2">
  <div class="Box-header f6">
    <p class="mb-0 text-bold">
      <a href="https://github.com/opencv/opencv/blob/c3e8a82c9c0b18432627fe100db332b42d64b8d3/modules/core/include/opencv2/core/private.hpp#L119">opencv/modules/core/include/opencv2/core/private.hpp</a>
    </p>
    <p class="mb-0 color-fg-muted">
         Line 119
      in
      <a data-pjax="true" class="commit-tease-sha" href="/opencv/opencv/commit/c3e8a82c9c0b18432627fe100db332b42d64b8d3">c3e8a82</a>
    </p>
  </div>
  <div itemprop="text" class="Box-body p-0 blob-wrapper blob-wrapper-embedded data">
    <table class="highlight tab-size mb-0 js-file-line-container" data-tab-size="8" data-paste-markdown-skip="">

        <tbody><tr class="border-0">
          <td id="L119" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="119"></td>
          <td id="LC119" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> #<span class="pl-k">define</span>  <span class="pl-en">CV_MALLOC_ALIGN</span>    <span class="pl-c1">64</span> </td>
        </tr>
    </tbody></table>
  </div>
</div>
<br>
there is a problem: if a small struct which is created by <code class="notranslate">new</code> is stored with cv::Mat, the memory increases a lot, if CV_MALLOC_ALIGN = 64, else it is normal when CV_MALLOC_ALIGN=8<p></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="#include &lt;thread&gt;
#include &lt;boost/circular_buffer.hpp&gt;
#include &lt;Eigen/Eigen&gt;
#include &lt;opencv2/core/core.hpp&gt;
#include &lt;stdlib.h&gt;
#include &lt;iostream&gt;

struct OdometryEigen
{
    Eigen::Matrix&lt;double, 6, 6&gt; p_cov;
    Eigen::Matrix&lt;double, 6, 6&gt; v_cov;
    Eigen::Matrix&lt;double, 3, 3&gt; R;
    Eigen::Matrix&lt;double, 3, 1&gt; t;
    Eigen::Matrix&lt;double, 6, 1&gt; v;
};

struct Impl
    uint32_t s;
    uint32_t ns;
};

struct TimestampOut
{
    TimestampOut()
        : impl_(new Impl)
    {
    }
    std::shared_ptr&lt;Impl&gt; impl_;
};


#define ALIGN_BYTE 8 

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

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

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

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

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

        return true;
    }

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

    void operator=(const AlignedMat&amp; 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&lt;std::thread&gt; add_thread = std::make_shared&lt;std::thread&gt;(&amp;addImage);
    add_thread-&gt;detach();

    // add odo
    addOdometry();

    return 0;
}

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

    for(; i &lt; num; i++)
    {
        // prepare data
        const uint16_t        width       = 1920u;
        const uint16_t        height      = 1080;
        const uint64_t        buffer_size = static_cast&lt;uint64_t&gt;(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 &lt;&lt; &quot;true&quot; &lt;&lt; std::endl;
        }
        else
        {
            std::cerr &lt;&lt; &quot;flase&quot; &lt;&lt; std::endl;
        }

        for(int i = 0;i &lt; (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 &lt;&lt; i &lt;&lt; &quot;th run \n&quot;;
        img_buffer.push_back(image);

        std::cerr &lt;&lt; &quot;image buffer size: &quot; &lt;&lt; img_buffer.size() &lt;&lt; std::endl;
    }

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

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

    for(; i &lt; num; i++)
    {

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

    return;
}"><pre class="notranslate"><code class="notranslate">#include &lt;thread&gt;
#include &lt;boost/circular_buffer.hpp&gt;
#include &lt;Eigen/Eigen&gt;
#include &lt;opencv2/core/core.hpp&gt;
#include &lt;stdlib.h&gt;
#include &lt;iostream&gt;

struct OdometryEigen
{
    Eigen::Matrix&lt;double, 6, 6&gt; p_cov;
    Eigen::Matrix&lt;double, 6, 6&gt; v_cov;
    Eigen::Matrix&lt;double, 3, 3&gt; R;
    Eigen::Matrix&lt;double, 3, 1&gt; t;
    Eigen::Matrix&lt;double, 6, 1&gt; v;
};

struct Impl
    uint32_t s;
    uint32_t ns;
};

struct TimestampOut
{
    TimestampOut()
        : impl_(new Impl)
    {
    }
    std::shared_ptr&lt;Impl&gt; impl_;
};


#define ALIGN_BYTE 8 

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

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

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

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

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

        return true;
    }

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

    void operator=(const AlignedMat&amp; 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&lt;std::thread&gt; add_thread = std::make_shared&lt;std::thread&gt;(&amp;addImage);
    add_thread-&gt;detach();

    // add odo
    addOdometry();

    return 0;
}

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

    for(; i &lt; num; i++)
    {
        // prepare data
        const uint16_t        width       = 1920u;
        const uint16_t        height      = 1080;
        const uint64_t        buffer_size = static_cast&lt;uint64_t&gt;(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 &lt;&lt; "true" &lt;&lt; std::endl;
        }
        else
        {
            std::cerr &lt;&lt; "flase" &lt;&lt; std::endl;
        }

        for(int i = 0;i &lt; (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 &lt;&lt; i &lt;&lt; "th run \n";
        img_buffer.push_back(image);

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

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

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

    for(; i &lt; num; i++)
    {

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

    return;
}
</code></pre></div>
<p dir="auto">thanks.</p>
<h5 dir="auto">System information (version)</h5>
<ul dir="auto">
<li>OpenCV =&gt; 4.1.1</li>
<li>Operating System / Platform =&gt; Ubuntu 18.04</li>
<li>Compiler =&gt; GCC 7.4.0</li>
</ul>
<h5 dir="auto">Detailed description</h5>
<p dir="auto">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.</p>
<p dir="auto">I've tried with OpenCV 3.4 as well, and the same thing happens</p>
<h5 dir="auto">Steps to reproduce</h5>
<p dir="auto">compile the following, run it and keep an eye on memory.</p>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#include &lt;thread&gt;
#include &lt;utility&gt;
#include &lt;vector&gt;
#include &lt;opencv2/core/mat.hpp&gt;

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&lt;std::string&gt; strings;

    for (size_t i = 0; i &lt; 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(&quot;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&quot;);
      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));
    }
}
"><pre class="notranslate">#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">&lt;</span>thread<span class="pl-pds">&gt;</span></span>
#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">&lt;</span>utility<span class="pl-pds">&gt;</span></span>
#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">&lt;</span>vector<span class="pl-pds">&gt;</span></span>
#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">&lt;</span>opencv2/core/mat.hpp<span class="pl-pds">&gt;</span></span>

<span class="pl-k">int</span> <span class="pl-en">main</span>() {
  
    <span class="pl-c"><span class="pl-c">//</span> minimum size for leak on my machine: 558995 x 1</span>
    cv::<span class="pl-c1">Size</span> <span class="pl-smi">size</span>(<span class="pl-c1">600000</span>, <span class="pl-c1">5</span>);
    cv::Mat <span class="pl-smi">tmp</span>(size, CV_8UC3, <span class="pl-c1">cv::Scalar</span>(<span class="pl-c1">0</span>, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>));

    std::vector&lt;std::string&gt; strings;

    <span class="pl-k">for</span> (<span class="pl-c1">size_t</span> i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">2000</span>; ++i)
    {
      cv::Mat <span class="pl-smi">tmp2</span>(size, CV_8UC3, <span class="pl-c1">cv::Scalar</span>(<span class="pl-c1">0</span>, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>));
      tmp = tmp2;

      <span class="pl-c"><span class="pl-c">//</span> needs to be suitably large, so it gets allocated on the heap</span>
      std::string <span class="pl-smi">val</span>(<span class="pl-s"><span class="pl-pds">"</span>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<span class="pl-pds">"</span></span>);
      strings.<span class="pl-c1">push_back</span>(val);

      <span class="pl-c"><span class="pl-c">//</span> gives you time to kill the process before it runs out of memory</span>
      <span class="pl-c1">std::this_thread::sleep_for</span>(<span class="pl-c1">std::chrono::milliseconds</span>(<span class="pl-c1">10</span>));
    }
}
</pre></div>
<p dir="auto">update:</p>
<p dir="auto">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.</p>