OpenCV 3.0 + Visual Studio Memory Leak Detector “false” positive

旧街凉风 提交于 2019-12-06 09:03:31

I solved the problem in a quite dirty way, but I didn't find better. The solution requires modifying one OpenCV file (system.cpp). If you found a better way to fix it, please leave a comment. I suppose more people might have similar problems.

First I tried to solve the problem using @JamesMcNellis solution (from comment above), by explicitly mark the block as _IGNORE_BLOCK: new (_IGNORE_BLOCK, __FILE__, __LINE__). It was really good start to solve this problem. Unfortunately the leak class contains members like e.g. std::vector, so tracing the allocations from this vector weren't suspended.

I started to read MSDN documentation to functions from crtdbg.h and I found a way to suspend memory leaks checking for a while. It's possible by clearing the flag '_CRTDBG_ALLOC_MEM_DF' using function: _CrtSetDbgFlag. Check details with example on MSDN: _CrtSetDbgFlag documentation. This solution has probably one drawback (one I know), It suspends memory leaks checking for all threads.

Finally using RAII and few macro definitions I created simple class to manage this functionality.

All the changes I applied to official 3.0 source codes.

Somewhere on top (after precomp.hpp include) of system.cpp file from OpenCV I added simple machinery:

#if defined(_MSC_VER) && defined(_DEBUG)
    #include <crtdbg.h>
    class MEMORY_LEAKS_CHECKING_SUSPENDER
    {
    public:
        MEMORY_LEAKS_CHECKING_SUSPENDER()
        {
            value = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
            int new_flag = value & (~_CRTDBG_ALLOC_MEM_DF);
            _CrtSetDbgFlag(new_flag);
        }

        ~MEMORY_LEAKS_CHECKING_SUSPENDER()
        {
            _CrtSetDbgFlag(value);
        }

    private:
        int value;
    };

    #define SUSPEND_MEMORY_LEAKS_CHECKING MEMORY_LEAKS_CHECKING_SUSPENDER suspend_memory_leaks_checking
#else
    #define SUSPEND_MEMORY_LEAKS_CHECKING
#endif

And each time I want to suspend memory leaks checking i have to add: PAUSE_MEMORY_LEAKS_CHECKING; It is enabled only in Visual Studio Debug compilation. The memory leaks tracing is automatically enabled after leaving the scope (destructor of MEMORY_LEAKS_CHECKING_SUSPENDER class).

Currently to suspend my OpenCV memory leaks I added suspending allocations in functions:

  • getTLSContainerStorage()
  • void* TLSDataContainer::getData() const
  • TLSData<CoreTLSData>& getCoreTlsData()
  • inline TLSStorage* TLSStorage::get()

(The last suspension in TLSStorage is probably fixed on master OpenCV repository - I briefly checked the repository)

Each modification is very simple (e.g. for first leak):

Before modification:

static TLSContainerStorage& getTLSContainerStorage()
{
    static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
    return *tlsContainerStorage;
}

After modification:

static TLSContainerStorage& getTLSContainerStorage()
{
    SUSPEND_MEMORY_LEAKS_CHECKING;
    static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
    return *tlsContainerStorage;
}

If you modify all these statements and still observe memory leaks and you use OpenCV as separately loaded dll then make sure you properly unloaded this dll using FreeLibrary function. For the reason check DLLMain function in OpenCV system.cpp file and cv::__termination variable usage.

I had the same problem in my project: statical build - MFC & OpenCV. Those solutions didn't help me. I tested them with OpenCV versions: 3.4.3 and 4.0.1. The issue went out when all opencv functions were into their own dlls. So my project configuration can be the following: MFC build - static, OpenCV - dynamic

Hexagonal

Ok, I have an alternative workaround:

Make a special function, say, prefetchOpenCvMemoryLeaks(), which creates/destroys a small matrix, creates/destroys a small window, and so on, so that OpenCV leaks are saturated.

In the outer main() function, save heap state with _CrtMemCheckpoint(), call the entire project, at the end save heap state again and compare it with the old one by _CrtMemDifference().

This way you can check your own memory leaks regardless of OpenCV ones.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!