gpt4 book ai didi

c++ - IShellDisptach:为什么 FolderItemVerbs::Release() + CoUninitialize() 会崩溃?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:23:56 36 4
gpt4 key购买 nike

IShellDispatch COM 接口(interface)有一个非常奇怪的问题,更具体地说是 FolderItemVerbs 对象,这让我抓狂!

调用 FolderItemVerbs::Release() 然后调用 CoUninitialze() 将导致崩溃。它显然是可重现的,但仅发生 10 次中的 1 次。

崩溃是“0xC0000005:访问冲突”错误。在循环中运行有问题的代码 100% 迟早会重现崩溃:-(

请看示例程序:

static int TestProc(const TCHAR *pcDirectoryName, const TCHAR *pcFileName)
{
int iSuccess = 0;

IShellDispatch *pShellDispatch = NULL;
Folder *pFolder = NULL; FolderItem *pItem = NULL;
FolderItemVerbs *pVerbs = NULL;

HRESULT hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&pShellDispatch);
if(FAILED(hr) || (pShellDispatch == NULL))
{
iSuccess = -3;
return iSuccess;
}

variant_t vaDirectory(pcDirectoryName);
hr = pShellDispatch->NameSpace(vaDirectory, &pFolder);
if(FAILED(hr) || (pFolder == NULL))
{
iSuccess = -4;
pShellDispatch->Release();
return iSuccess;
}

variant_t vaFileName(pcFileName);
hr = pFolder->ParseName(vaFileName, &pItem);
if(FAILED(hr) || (pItem == NULL))
{
iSuccess = -5;
pFolder->Release();
pShellDispatch->Release();
return iSuccess;
}

hr = pItem->Verbs(&pVerbs);
if(FAILED(hr) || (pVerbs == NULL))
{
iSuccess = -6;
pItem->Release();
pFolder->Release();
pShellDispatch->Release();
return iSuccess;
}

/* Here we would do something with the FolderItemVerbs */

pVerbs->Release(); pVerbs = NULL; //If this line is commented out, we don't get a crash, but a massive memory leak!
pItem->Release(); pItem = NULL;
pFolder->Release(); pFolder = NULL;
pShellDispatch->Release(); pShellDispatch = NULL;

iSuccess = 1;
return iSuccess;
}

//-----------------------------------------------------------------------------

static unsigned __stdcall ThreadProc(void* pArguments)
{
HRESULT hr = CoInitialize(NULL);
if((hr == S_OK) || (hr == S_FALSE))
{
threadParam_t *params = (threadParam_t*) pArguments;
params->returnValue = TestProc(params->pcDirectoryName, params->pcFileName);
CoUninitialize();
}
else
{
if(threadParam_t *params = (threadParam_t*) pArguments)
{
params->returnValue = -10;
}
}

return EXIT_SUCCESS;
}

请在此处下载完整示例代码: http://pastie.org/private/0xsnajpia9lsmgnlf2afa

另请注意,我明确追踪到 FolderItemVerbs 崩溃,因为如果我从未创建 FolderItemVerbs 对象,崩溃会立即消失。

此外,如果我从不在 CoUninitialize() 之前调用“pVerbs->Release()”,崩溃也会消失,但这显然会导致大量内存泄漏。

另一件奇怪的事情是,如果我在调试器下运行程序,崩溃将不会发生!但我可以运行程序,等待崩溃,然后让调试器处理崩溃。

不幸的是,我得到的堆栈跟踪并没有多大帮助: http://pastie.org/private/cuwunlun2t5dc5lembpw

我不认为我在这里做错了什么。这两天我一遍又一遍地检查代码。所以这一切似乎都是 FolderItemVerbs 中的错误!

有没有人以前遇到过这个和/或可以确认这是 FolderItemVerbs 中的错误?另外,这个问题有什么解决方法吗?

提前致谢!!!

最佳答案

谢谢大家!

这是执行显式消息调度的“更正”代码:

void DispatchPendingMessages(void)
{
const DWORD uiTimeout = GetTickCount() + 10000;
const HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
unsigned int counter = 0;
if(hEvent)
{
for(;;)
{
MSG Message;
while(PeekMessage(&Message, NULL, WM_NULL, WM_NULL, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
const DWORD nWaitResult = MsgWaitForMultipleObjects(1, &hEvent, FALSE, 250, QS_ALLINPUT | QS_ALLPOSTMESSAGE);
if((nWaitResult == WAIT_TIMEOUT) || (nWaitResult == WAIT_FAILED) || (GetTickCount() >= uiTimeout)) break;
}
CloseHandle(hEvent);
}
}

//-----------------------------------------------------------------------------

static int TestProc(const TCHAR *pcDirectoryName, const TCHAR *pcFileName)
{
int iSuccess = 0;

IShellDispatch *pShellDispatch = NULL;
Folder *pFolder = NULL; FolderItem *pItem = NULL;
FolderItemVerbs *pVerbs = NULL;

HRESULT hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&pShellDispatch);
if(FAILED(hr) || (pShellDispatch == NULL))
{
iSuccess = -3;
return iSuccess;
}

variant_t vaDirectory(pcDirectoryName);
hr = pShellDispatch->NameSpace(vaDirectory, &pFolder);
if(FAILED(hr) || (pFolder == NULL))
{
iSuccess = -4;
pShellDispatch->Release();
return iSuccess;
}

variant_t vaFileName(pcFileName);
hr = pFolder->ParseName(vaFileName, &pItem);
if(FAILED(hr) || (pItem == NULL))
{
iSuccess = -5;
pFolder->Release();
pShellDispatch->Release();
return iSuccess;
}

hr = pItem->Verbs(&pVerbs);
if(FAILED(hr) || (pVerbs == NULL))
{
iSuccess = -6;
pItem->Release();
pFolder->Release();
pShellDispatch->Release();
return iSuccess;
}

/* Here we would do something with the FolderItemVerbs */

pVerbs->Release(); pVerbs = NULL;
pItem->Release(); pItem = NULL;
pFolder->Release(); pFolder = NULL;
pShellDispatch->Release(); pShellDispatch = NULL;

iSuccess = 1;
return iSuccess;
}

//-----------------------------------------------------------------------------

static unsigned __stdcall ThreadProc(void* pArguments)
{
HRESULT hr = CoInitialize(NULL);
if((hr == S_OK) || (hr == S_FALSE))
{
threadParam_t *params = (threadParam_t*) pArguments;
params->returnValue = TestProc(params->pcDirectoryName, params->pcFileName);
DispatchPendingMessages(); //This is required before CoUninitialize() to avoid crash with certain Shell Extensions !!!
CoUninitialize();
}
else
{
if(threadParam_t *params = (threadParam_t*) pArguments)
{
params->returnValue = -10;
}
}

return EXIT_SUCCESS;
}

到目前为止,那个代码无法重现崩溃:-)

关于c++ - IShellDisptach:为什么 FolderItemVerbs::Release() + CoUninitialize() 会崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13018389/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com