2013-03-07 26 views
0

我已經複製並修改了一段代碼msdnwmi密碼泄露

其內存泄漏。請幫忙。

#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

你怎麼知道它是否漏水更換你全部搞定電話?你觀察到泄漏發生的條件是什麼?你知道它什麼時候發生?泄漏有多大?它多久發生一次? – quetzalcoatl 2013-03-07 13:16:59

回答

0

檢查IWebmServices::Get的文檔還您變種clearence是錯誤的,你基本上是濫用其使用情況,考慮將你的變種decleration和釋放內部的循環。您通過引用獲取變體,在完成每個變體之後,您應該在獲取apObjArray中下一個對象的屬性之前將其清除,因爲您將獲得不同的對象。你的代碼所做的只是釋放每個變體的最後一個引用。此外,由於您正在爲所有Get調用使用相同的HRESULT對象,這意味着如果有任何調用失敗,您將不會釋放這些屬性並導致泄漏。

考慮這個替換代碼:

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. 
    } 


} 

考慮這個