我已复制并修改了msdn的一段代码。
它的泄漏记忆。请帮忙。
#include "querysink.h"
int main(int argc, char **argv)
{
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1;
}
QuerySink* pResponseSink = new QuerySink();
hres = pSvc->ExecQueryAsync(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_NTLogEvent"),
WBEM_FLAG_BIDIRECTIONAL,
NULL,
pResponseSink);
if (FAILED(hres))
{
cout << "Query for log collection failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
pResponseSink->Release();
CoUninitialize();
return 1;
}
while(pResponseSink->IsDone()==false){
Sleep(100);
}
pSvc->Release();
pLoc->Release();
CoUninitialize();
while(1)
{
//do other job here
}
return 0; // Program successfully completed.
}//end of file
// querysink.cpp
#include "querysink.h"
ULONG QuerySink::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
ULONG QuerySink::Release()
{
LONG lRef = InterlockedDecrement(&m_lRef);
if(lRef == 0)
delete this;
return lRef;
}
HRESULT QuerySink::QueryInterface(REFIID riid, void** ppv)
{
if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
{
*ppv = (IWbemObjectSink *) this;
AddRef();
return WBEM_S_NO_ERROR;
}
else return E_NOINTERFACE;
}
HRESULT QuerySink::Indicate(long lObjectCount,
IWbemClassObject **apObjArray)
{
HRESULT hres = S_OK;
VARIANT writtenTime,genTime,logFile,eventCode,eventId,eventType,category;
for (int i = 0; i < lObjectCount; i++)
{
hres = apObjArray[i]->Get(L"TimeWritten", 0, &writtenTime, 0, 0);
hres = apObjArray[i]->Get(L"TimeGenerated", 0, &genTime, 0, 0);
hres = apObjArray[i]->Get(L"Logfile", 0, &logFile, 0, 0);
hres = apObjArray[i]->Get(L"Category", 0, &category, 0, 0);
hres = apObjArray[i]->Get(L"EventCode", 0, &eventCode, 0, 0);
hres = apObjArray[i]->Get(L"EventIdentifier", 0, &eventId, 0, 0);
hres = apObjArray[i]->Get(L"EventType", 0, &eventType, 0, 0);
//如果我删除7行以上,那么内存消耗就可以了。
if (FAILED(hres))
{
cout << "Failed to get the data from the query"
<< " Error code = 0x"
<< hex << hres << endl;
return WBEM_E_FAILED; // Program has failed.
}
}
VariantClear(&writtenTime);
VariantClear(&genTime);
VariantClear(&category);
VariantClear(&eventCode);
VariantClear(&eventId);
VariantClear(&eventType);
VariantClear(&logFile);
return WBEM_S_NO_ERROR;
}
HRESULT QuerySink::SetStatus(
/* [in] */ LONG lFlags,
/* [in] */ HRESULT hResult,
/* [in] */ BSTR strParam,
/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
)
{
if(lFlags == WBEM_STATUS_COMPLETE)
{
printf("Call complete.\n");
EnterCriticalSection(&threadLock);
bDone = true;
LeaveCriticalSection(&threadLock);
}
else if(lFlags == WBEM_STATUS_PROGRESS)
{
printf("Call in progress.\n");
}
return WBEM_S_NO_ERROR;
}
bool QuerySink::IsDone()
{
bool done = true;
// EnterCriticalSection(&threadLock);
done = bDone;
// LeaveCriticalSection(&threadLock);
return done;
} // end of querysink.cpp
// querysink.h
#ifndef QUERYSINK_H
#define QUERYSINK_H
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
class QuerySink : public IWbemObjectSink
{
LONG m_lRef;
bool bDone;
CRITICAL_SECTION threadLock; // for thread safety
public:
QuerySink() { m_lRef = 0; bDone = false;
InitializeCriticalSection(&threadLock); }
~QuerySink() { bDone = true;
DeleteCriticalSection(&threadLock); }
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
void** ppv);
virtual HRESULT STDMETHODCALLTYPE Indicate(
LONG lObjectCount,
IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
);
virtual HRESULT STDMETHODCALLTYPE SetStatus(
/* [in] */ LONG lFlags,
/* [in] */ HRESULT hResult,
/* [in] */ BSTR strParam,
/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
);
bool IsDone();
};
#endif // end of querysink.h
答案 0 :(得分:0)
检查IWebmServices::Get的文档,你的变体清除是错误的,你基本上滥用它的用法,考虑移动decleration并释放你的变量在for循环中。您将通过引用获取变体,在完成每个变体后,您应该在获取apObjArray
中的下一个对象的属性之前将其清除,因为您将获得不同的对象。您的代码所做的只是免费提取每个变体的最后一个参考。此外,由于您对所有HRESULT
调用使用相同的Get
对象,这意味着如果任何调用失败,您将无法释放属性,这将导致泄漏。
考虑用以下代码替换代码:
for (int i = 0; i < lObjectCount; i++)
{
VARIANT writtenTime,genTime,logFile,eventCode,eventId,eventType,category;
BSTR strTimeWrittenProp = SysAllocString(L"TimeWritten");
hres = apObjArray[i]->Get(strTimeWrittenProp, 0, &writtenTime, 0, 0);
SysFreeString(strTimeWrittenProp);
//... Get other properties
VariantClear( &writtenTime );
//..clear variants before moving to next object in array
enter code here
if (FAILED(hres))
{
cout << "Failed to get the data from the query"
<< " Error code = 0x"
<< hex << hres << endl;
return WBEM_E_FAILED; // Program has failed.
}
}
考虑用此
替换所有的来电