【问题标题】:WMI memory leak issueWMI 内存泄漏问题
【发布时间】:2017-04-08 20:19:11
【问题描述】:

我在更改语言时遇到了一些WMI 内存泄漏问题。我已经在Task Manager 中检查过了。例如,我的应用程序占用 25 MB RAM,当更改语言时它会增长到 30 MB 和 35、40...并且永远不会释放它。

//Initialization
IWbemLocator *pLocator = 0;
IWbemServices *pService = 0;
IEnumWbemClassObject* pEnumerator = NULL;
IWbemClassObject *pclsObj = NULL;

while (pEnumerator)
{
      hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

      VARIANT processName;
      pclsObj->Get(L"Name", 0, &processName, 0, 0);
      QString userProcessName;
      userProcessName = QString::fromWCharArray(processName.bstrVal);

      emit testData(userProcessName);
      VariantClear(&processName);
}

//Cleanup
 pService->Release();
 pLocator->Release();
 //pEnumerator->Release(); - Clang Static Analyzer displays issue - called C++ object pointer is null
 //pclsObj->Release(); - Clang Static Analyzer displays issue - called C++ object pointer is null

如何解决这个问题?提前致谢。

我检查过内存泄漏的测试截图:

代码:

int Test::allServicesWMIData()
{
    HRESULT hres;

    // Initialize COM.
    hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED);

    if (FAILED(hres))
    {
        emit initComLibError(QString(QObject::tr("Failed to initialize COM library. Error code =") + " 0x%1").arg(hexErrorData(hres)));
        return 1;              // Program has failed.
    }

    IWbemLocator *pLocator = 0;

    hres = CoCreateInstance(
        CLSID_WbemLocator,
        0,
        CLSCTX_INPROC_SERVER,
        IID_IWbemLocator, (LPVOID *)&pLocator);

    if (FAILED(hres))
    {
        emit errorCreateIWbemObject(QString(QObject::tr("Failed to create IWbemLocator object. Error code =") + " 0x%1").arg(hexErrorData(hres)));
        CoUninitialize();
        return 1;       // Program has failed.
    }

    IWbemServices *pService = 0;

    hres = pLocator->ConnectServer(
        _bstr_t(L"ROOT\\CIMV2"), // WMI namespace
        NULL,                    // User name
        NULL,                    // User password
        0,                       // Locale
        NULL,                    // Security flags
        0,                       // Authority
        0,                       // Context object
        &pService                    // IWbemServices proxy
    );

    if (FAILED(hres))
    {
        emit errorRootConnection(QString(QObject::tr("Could not connect. Error code =") + " 0x%1").arg(hexErrorData(hres)));
        pLocator->Release();
        CoUninitialize();
        return 1;                // Program has failed.
    }

    hres = CoSetProxyBlanket(
        pService,                         // the proxy to set
        RPC_C_AUTHN_WINNT,            // authentication service
        RPC_C_AUTHZ_NONE,             // authorization service
        NULL,                         // Server principal name
        RPC_C_AUTHN_LEVEL_CALL,       // authentication level
        RPC_C_IMP_LEVEL_IMPERSONATE,  // impersonation level
        NULL,                         // client identity
        EOAC_NONE                     // proxy capabilities
    );

    if (FAILED(hres))
    {
        emit errorProxyBlanket(QString(QObject::tr("Could not set proxy blanket. Error code =") + " 0x%1").arg(hexErrorData(hres)));
        pService->Release();
        pLocator->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pService->ExecQuery(
        bstr_t("WQL"),
        bstr_t("SELECT * FROM Win32_Service"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
        NULL,
        &pEnumerator);

    IWbemClassObject *pclsObj = NULL;

    if (FAILED(hres))
    {
        emit errorProcessQuery(QString(QObject::tr("Query for processes failed. Error code =") + " 0x%1").arg(hexErrorData(hres)));
        pService->Release();
        pLocator->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }
    else
    {
        ULONG uReturn = 0;

        while (pEnumerator)
        {
            hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

            VARIANT serviceName;
            VARIANT servicePath;
            VARIANT serviceID;
            VARIANT serviceType;
            VARIANT serviceState;
            VARIANT serviceStatus;
            VARIANT serviceErrorControl;
            VARIANT serviceStartMode;
            VARIANT serviceWaitHint;
            VARIANT serviceExitCode;

            if (hres != 0) {
                emit hardwareDataNotAvailable();
                break;
            } else {
                pclsObj->Get(L"Caption", 0, &serviceName, 0, 0);
                pclsObj->Get(L"PathName", 0, &servicePath, 0, 0);
                pclsObj->Get(L"ProcessId", 0, &serviceID, 0, 0);
                pclsObj->Get(L"ServiceType", 0, &serviceType, 0, 0);
                pclsObj->Get(L"State", 0, &serviceState, 0, 0);
                pclsObj->Get(L"Status", 0, &serviceStatus, 0, 0);
                pclsObj->Get(L"ErrorControl", 0, &serviceErrorControl, 0, 0);
                pclsObj->Get(L"StartMode", 0, &serviceStartMode, 0, 0);
                pclsObj->Get(L"WaitHint", 0, &serviceWaitHint, 0, 0);
                pclsObj->Get(L"ExitCode", 0, &serviceExitCode, 0, 0);
            }

            QString userServiceName = QString::fromWCharArray(serviceName.bstrVal);
            QString userServicePath = QString::fromWCharArray(servicePath.bstrVal);
            QString userServiceID = QString::number(serviceID.uintVal);
            QString userServiceType = QString::fromWCharArray(serviceType.bstrVal);
            QString userServiceState = QString::fromWCharArray(serviceState.bstrVal);
            QString userServiceStatus = QString::fromWCharArray(serviceStatus.bstrVal);
            QString userServiceErrorControl = QString::fromWCharArray(serviceErrorControl.bstrVal);
            QString userServiceStartMode = QString::fromWCharArray(serviceStartMode.bstrVal);
            QString userServiceWaitHint = QString::number(serviceWaitHint.uintVal);
            QString userServiceExitCode = QString::number(serviceExitCode.uintVal);

            emit appAllServicesData(userServiceName, userServicePath, userServiceID, userServiceType, userServiceState, userServiceStatus, userServiceErrorControl,
            userServiceStartMode, userServiceWaitHint, userServiceExitCode);

            VariantClear(&serviceName);
            VariantClear(&servicePath);
            VariantClear(&serviceID);
            VariantClear(&serviceType);
            VariantClear(&serviceState);
            VariantClear(&serviceStatus);
            VariantClear(&serviceErrorControl);
            VariantClear(&serviceStartMode);
            VariantClear(&serviceWaitHint);
            VariantClear(&serviceExitCode);
        }
    }

    // Cleanup
    pService->Release();
    pLocator->Release();
    //pEnumerator->Release(); - Clang Static Analyzer displays issue - called C++ object pointer is null
    //pclsObj->Release(); - Clang Static Analyzer displays issue - called C++ object pointer is null
    CoUninitialize();
    emit finished();
    return 0;   // Program successfully completed.
}

【问题讨论】:

  • 任务管理器中没有一列显示进程占用的 RAM 量。你真正在看什么价值?为什么你认为存在内存泄漏?确保你理解memory management
  • 如果您需要发布屏幕截图,请将其放在您的问题中。并使用受支持的图像主机。 fastpic.ru 不是受支持的图像主机。
  • 我的应用程序占用了内存并且从不释放它,所以我应该认为这不是泄漏吗?
  • 这可能是也可能不是泄漏,我们不知道。查看您发布的代码,内存泄漏可能是您最不担心的问题。如发布的那样,该代码立即使进程因访问冲突而崩溃。我建议发布真实代码。
  • 那个"minimal"怎么样?此外,既然你标记了这个问题c++,你为什么不使用智能指针?这将节省您实现手动资源管理的代码的三分之一。我不知道,为什么你也评论了pEnumerator->Release();。这是记录在案的资源泄漏(请参阅IWbemServices::ExecQuery)。另外,您似乎对 COM 的理解不够深入,无法完成此操作(例如,您的 VARIANTs 都没有被初始化)。

标签: c++ qt memory-leaks windows-applications


【解决方案1】:

@IInspectable

谢谢。我已经通过释放资源修复了WMI内存泄漏问题。

代码:

...
            VariantClear(&serviceName);
            VariantClear(&servicePath);
            VariantClear(&serviceID);
            VariantClear(&serviceType);
            VariantClear(&serviceState);
            VariantClear(&serviceStatus);
            VariantClear(&serviceErrorControl);
            VariantClear(&serviceStartMode);
            VariantClear(&serviceWaitHint);
            VariantClear(&serviceExitCode);
            pclsObj->Release();
        }
    }

    // Cleanup
    pService->Release();
    pLocator->Release();
    pEnumerator->Release();
    CoUninitialize();
    emit finished();
    return 0;   // Program successfully completed.
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-28
    相关资源
    最近更新 更多