Решил проблему довольно грязно, но лучше не нашел. Решение требует изменения одного файла OpenCV (system.cpp). Если вы нашли способ исправить это лучше, оставьте, пожалуйста, комментарий. Я полагаю, что подобные проблемы могут быть у большего количества людей.
Сначала я попытался решить проблему с помощью решения @JamesMcNellis (из комментария выше), явно пометив блок как _IGNORE_BLOCK: new (_IGNORE_BLOCK, __FILE__, __LINE__)
. Это было действительно хорошее начало для решения этой проблемы. К сожалению, класс утечки содержит такие члены, как, например, std::vector
, поэтому отслеживание выделений из этого вектора не было приостановлено.
Я начал читать документацию MSDN к функциям из crtdbg.h
и нашел способ на время приостановить проверку утечек памяти. Это возможно, сняв флаг '_CRTDBG_ALLOC_MEM_DF' с помощью функции: _CrtSetDbgFlag
. Подробности см. В примере в MSDN: _CrtSetDbgFlag документация. У этого решения, вероятно, есть один недостаток (который я знаю): оно приостанавливает проверку утечек памяти для всех потоков.
Наконец, используя RAII и несколько определений макросов, я создал простой класс для управления этой функциональностью.
Все изменения я применил к официальным исходным кодам 3.0.
Где-то наверху (после включения precomp.hpp) system.cpp
файла из OpenCV я добавил простую технику:
#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
И каждый раз, когда я хочу приостановить проверку утечек памяти, я должен добавить: PAUSE_MEMORY_LEAKS_CHECKING;
Он включен только в компиляции Visual Studio Debug. Трассировка утечек памяти включается автоматически после выхода из области видимости (деструктор класса MEMORY_LEAKS_CHECKING_SUSPENDER
).
В настоящее время, чтобы приостановить утечки памяти OpenCV, я добавил приостановку выделения в функциях:
getTLSContainerStorage()
void* TLSDataContainer::getData() const
TLSData<CoreTLSData>& getCoreTlsData()
inline TLSStorage* TLSStorage::get()
(Последняя приостановка в TLSStorage, вероятно, исправлена в главном репозитории OpenCV - я кратко проверил репозиторий)
Каждая модификация очень проста (например, для первой утечки):
Перед модификацией:
static TLSContainerStorage& getTLSContainerStorage()
{
static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
return *tlsContainerStorage;
}
После модификации:
static TLSContainerStorage& getTLSContainerStorage()
{
SUSPEND_MEMORY_LEAKS_CHECKING;
static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
return *tlsContainerStorage;
}
Если вы изменяете все эти операторы и по-прежнему наблюдаете утечки памяти и используете OpenCV как отдельно загруженную dll, убедитесь, что вы правильно выгрузили эту dll с помощью функции FreeLibrary
. По этой причине проверьте функцию DLLMain
в system.cpp
файле OpenCV и использование cv::__termination
переменной.
person
AdamF
schedule
06.10.2015
getCoreTlsData()
, чтобы явно передать тип блока оператору отладки new, напримерnew (_IGNORE_BLOCK, __FILE__, __LINE__) TlsData<CoreTLSData>()
. В качестве альтернативы (но еще хуже) вы можете освободить блок самостоятельно, прежде чем выполнять проверку на утечку, черезdelete &getCoreTlsData();
. Но это потребует тщательного выбора времени: вам нужно будет убедиться, что вы сделали это после OpenCv, используя его. - person James McNellis   schedule 05.10.2015