0

我从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
4

1 回答 1

0

检查IWebmServices::Get的文档,你的变体清除也是错误的,你基本上是在滥用它的用法,考虑在 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.
    }


}

考虑用这个替换你所有的 get 调用

于 2013-03-07T13:38:59.590 回答