Утечка памяти в IWbemServices-> ExecNotificationQuery?

У меня есть код, связанный с WMI, который получает событие после запуска нового приложения.
Я пропустил часть инициализации, вот код. Обратите внимание, что все работает, все HRESULT S_OK.

IEnumWbemClassObject* pEnumerator = NULL;

pSvc->ExecNotificationQuery( // IWbemServices *pSvc is initialized
bstr_t("WQL"),
bstr_t("SELECT * FROM __InstanceCreationEvent WITHIN 1 ""WHERE TargetInstance ISA 'Win32_Process'"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &pEnumerator);

while (pEnumerator) {
_variant_t v1, v2;
pclsObj->Get(_bstr_t(L"TargetInstance"), 0, &v1, 0, 0);
IUnknown* str = v1;
str->QueryInterface(IID_IWbemClassObject, reinterpret_cast< void** >(&pclsObj));
pclsObj->Get(bstr_t(L"Handle"), 0, &v2, 0, 0);
LONG pid{ 0 };
hr = VarI4FromStr(v2.bstrVal, LOCALE_NOUSEROVERRIDE, 409, &pid);
Internal::Inject(pid); // It's my code, not relevant here

str->Release();
pclsObj->Release();
v1.Clear();
v2.Clear();
}

Этот код был взят из MSDN и немного изменен. Тем не менее, это утечка памяти, и я понятия не имею, почему. Просматривая через профилировщик памяти MSVC, мы получаем следующую картину:
screen1

или это:
screen2

С моей точки зрения — я все очистил \ отпустил, однако распределения, как на скриншотах, происходят, когда приходят новые события, и они остаются навсегда.

я обнаружил этот вопрос, кажется, что это то же самое, но ответа не получено.

Visual Studio 2015, обновление 3, последняя версия Windows 10 x64 Professional.

-1

Решение

Когда вы звоните str->QueryInterface()Вы переопределяете pclsObj указатель без вызова pclsObj->Release() заранее. Ты звонишь Release() на pclsObj возражать, что QueryInterface() возвращается, и утечка оригинала pclsObj объект.

Вам следует прекратить управлять счетчиками ссылок интерфейса вручную и использовать _com_ptr_t обертка вместо.

Где оригинал pclsObj приходящий из? Похоже, вы пропустили звонок pEnumerator->Next(),

Вместо этого попробуйте что-то вроде этого (обработка ошибок для краткости опущена):

_com_ptr_t<IEnumWbemClassObject> pEnumerator;

pSvc->ExecNotificationQuery( // IWbemServices *pSvc is initialized
bstr_t("WQL"),
bstr_t("SELECT * FROM __InstanceCreationEvent WITHIN 1 ""WHERE TargetInstance ISA 'Win32_Process'"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &pEnumerator);

if (pEnumerator)
{
while (true)
{
_com_ptr_t<IWbemClassObject> pclsEvent, pclsObj;
_variant_t v1, v2;
ULONG ulReturned = 0;

pEnumerator->Next(WBEM_INFINITE, 1, &pclsEvent, &ulReturned);
pclsEvent->Get(_bstr_t(L"TargetInstance"), 0, &v1, 0, 0);

_com_ptr_t<IUnknown> str = v1;
str->QueryInterface(IID_IWbemClassObject, reinterpret_cast<void**>(&pclsObj));
pclsObj->Get(bstr_t(L"Handle"), 0, &v2, 0, 0);

LONG pid{ 0 };
hr = VarI4FromStr(v2.bstrVal, LOCALE_NOUSEROVERRIDE, 409, &pid);
Internal::Inject(pid); // It's my code, not relevant here
}
}

В качестве альтернативы:

_com_ptr_t<IEnumWbemClassObject> pEnumerator;

pSvc->ExecNotificationQuery( // IWbemServices *pSvc is initialized
bstr_t("WQL"),
bstr_t("SELECT * FROM __InstanceCreationEvent WITHIN 1 ""WHERE TargetInstance ISA 'Win32_Process'"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &pEnumerator);

if (pEnumerator)
{
while (true)
{
_com_ptr_t<IWbemClassObject> pclsObj;
_variant_t v1, v2;
ULONG ulReturned = 0;

pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &ulReturned);
pclsObj->Get(_bstr_t(L"TargetInstance"), 0, &v1, 0, 0);

// _com_ptr_t::operator&() calls Release() on the current object
// if not NULL before then returning the address of the the
// interface pointer...

_com_ptr_t<IUnknown> str = v1;
str->QueryInterface(IID_IWbemClassObject, reinterpret_cast<void**>(&pclsObj));
pclsObj->Get(bstr_t(L"Handle"), 0, &v2, 0, 0);

LONG pid{ 0 };
hr = VarI4FromStr(v2.bstrVal, LOCALE_NOUSEROVERRIDE, 409, &pid);
Internal::Inject(pid); // It's my code, not relevant here
}
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]