为什么这个COM代码会泄漏
Why is this COM code leaking?
我正在维护一个使用Windows资源管理器覆盖图标的应用程序。有时,某些操作要求我强制刷新特定文件夹的浏览器视图。我使用以下使用COM的函数:
void RefreshExplorerView(CString strPath)
{
CComPtr<IShellWindows> pShellWindows;
CoInitialize(NULL);
if(SUCCEEDED(pShellWindows.CoCreateInstance(CLSID_ShellWindows)))
{
IDispatch* pFolder=NULL;
VARIANT variant;
V_VT(&variant) = VT_I4;
for(V_I4(&variant) = 0; pShellWindows->Item(variant, &pFolder) == S_OK; V_I4(&variant)++)
{
CComPtr<IWebBrowserApp> pWebBrowserApp;
if(SUCCEEDED(pFolder->QueryInterface(IID_PPV_ARGS(&pWebBrowserApp))))
{
BSTR LocationURL = NULL;
pWebBrowserApp->get_LocationURL(&LocationURL);
if(LocationURL != NULL && strPath.CompareNoCase(LocationURL) == 0)
{
CComPtr<IServiceProvider> pServiceProvider;
if(SUCCEEDED(pWebBrowserApp->QueryInterface(IID_PPV_ARGS(&pServiceProvider))))
{
CComPtr<IShellBrowser> pShellBrowser;
if(SUCCEEDED(pServiceProvider->QueryInterface(IID_PPV_ARGS(&pShellBrowser))))
{
IShellView* pShellView;
if(SUCCEEDED(pShellBrowser->QueryActiveShellView(&pShellView)))
{
pShellView->Refresh();
pShellView->Release();
}
}
}
}
SysFreeString(LocationURL);
}
pFolder->Release();
pFolder = NULL;
}
}
CoUninitialize();
}
我注意到,当我的程序定期刷新时,它的大小会慢慢增长,UMDH告诉我,每次运行时,我似乎都在泄漏pFolder
和pShellWindow
实例。我不知道为什么会发生这种情况,因为据我所知,这些都是正确释放的。有人知道我错过了什么吗?
在CoUninitialize
之后释放pShellWindows
,这是错误的。
其余的接口似乎发布得很好。请注意,您可以通过使用CComQIPtr
而不是QueryInterface
,并且根本不使用原始指针(BSTR
, IFoo*
)并将它们替换为智能自动释放包装器,从而大大改善整洁性和可读性。如果Item
调用成功但返回S_OK
以外的代码,
pFolder
也可能泄漏。同样,使用CComPtr<IFolder>
代替IFolder*
可以立即解决这个问题,甚至不会引起任何注意。
CoInitialize(NULL);
这个语句有不止一个问题。@Roman解释了过早不初始化是如何造成泄漏的。但是这也会以不止一种方式变坏,线程的公寓状态在COM中是一个真正的大问题:
您没有检查CoInitialize()的返回值。如果客户端应用程序已经调用了CoInitializeEx(),并且选择了MTA而不是STA,那么调用该函数的客户端应用程序就会崩溃。这将使CoInitialize()失败,你不能在提交后更改线程状态。你的CoUninitialize()调用将会把客户端应用搞得一团糟,导致后续的所有COM调用都失败。
选择STA还要求您实现单线程公寓的合同。它声明你永远不会阻塞线程,你可以这样做。和表示您泵入消息循环。消息循环对于封送对单线程单元的调用至关重要。对于,您不能,也不能合理地确保在这样的函数中考虑到这一点。对于shell接口来说尤其重要的是,它们中的绝大多数都不是线程安全的。不抽运的后果是死锁。您可以不抽吸,但这并不能保证死锁。这里您可以有一点余地,因为这些可能是进程外接口。
特别是最后一个要求只能由创建调用这个函数的线程的代码来满足,只有它可以控制线程在调用你的函数之外做什么。如果你不能保证客户端应用程序正确初始化COM,那么唯一真正安全的事情就是自己创建一个线程。
- 为什么以下C++代码中存在内存泄漏?
- 无法找出我的代码中的内存泄漏
- 如何防止使用 std::shared_ptr 的代码中的内存泄漏
- 为什么当为T2抛出bad_alloc异常时,此代码中会发生内存泄漏
- 以下代码是否存在内存泄漏?
- C++/CLI 代码中的内存泄漏
- 客户端代码中的 Valgrind 钩子:特定函数的内存泄漏
- 我的C++代码中是否有一些内存泄漏
- 为什么 heob 在 QCreator 生成的代码中将这些检测为内存泄漏
- 尝试在我的 C++ 代码中查找内存泄漏
- 以下代码中的嵌入"new"是否会导致内存泄漏?
- 如何解决C++代码中的内存泄漏问题
- 泄漏测试代码shared_ptr奇怪的结果
- 内存泄漏在0行代码中
- 为什么在此OpenCL代码中泄漏内存,为什么要泄漏内存
- QaudioOutput代码是否有任何内存泄漏
- 此代码是否会导致内存泄漏问题
- 避免在JNI代码中的内存泄漏
- 如果您以Java JNI分配的本机代码中的内存泄漏,会发生什么
- 你能在这个代码中找到 4 字节的内存泄漏吗?