I would like to create project with enabled Visual Studio memory leak detector (Memory Leak Detector)
It always worked fine and I could easily find memory leaks by running bunch of tests on my application and then checking the report.
But after statically linking OpenCV 3.0 to my project I got some false positives.
For instance the most frustrating error comes from StereoBMImpl::compute
method and call: ocl::useOpenCL()
After debugging I found the source of the "leak":
TLSData<CoreTLSData>& getCoreTlsData()
{
static TLSData<CoreTLSData> *value = new TLSData<CoreTLSData>();
return *value;
}
After analyzing this code we know the static object is allocated only once and everything should be OK. But now I have bunch of false positive memory leak reports like:
{1370349} normal block at 0x0E74D560, 24 bytes long.
Data: < > FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
{1370348} normal block at 0x0E74D4E0, 64 bytes long.
Data: <` t > 60 D5 74 0E CD CD CD CD CD CD CD CD CD CD CD CD
And now it's very difficult to find some real memory leaks in my application because there is set of false positives from OpenCV. I can't also run automatic memory leak tests because the output always contains some leaks.
Is there any way to remove these "pseudo" errors (if possible without changing OpenCV source code) ? It's very annoying.
I suppose other memory leaks detectors will also report some similar pseudo leaks because the new
operator is executed without delete
(object is automatically cleaned up by the OS).
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
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 thatOpenCV
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.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: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 ofMEMORY_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:
After modification:
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 checkDLLMain
function in OpenCVsystem.cpp
file andcv::__termination
variable usage.