导致堆失败的原因 [英] propget cause heap failure
问题描述
大家好,
我正在使用COM为MFC/控制台应用程序提供一些日期.但是遇到一些堆堆失败的情况.
以下是场景:
1.定义propget方法
Hi Guys,
I was using a COM to provide some date for MFC/Console app. But encounter some propget heap failure.
Following is the scenario:
1. Define the propget method
HRESULT m_ProcessName([out, string, retval] OLECHAR** pVal);
正文:
Body:
STDMETHODIMP CExProcessInfo::get_m_ProcessName(OLECHAR** pVal)
{
// TODO: Add your implementation code here
if(m_pProcessName == NULL)
*pVal = (OLECHAR*)::SysAllocString(L"");
else
*pVal = (OLECHAR*)::SysAllocString(m_pProcessName);
return S_OK;
}
2.在客户端上调用方法:
2. Call the method on client:
WCHAR* pProcName = new WCHAR[MAX_PATH];
pep[i]->get_m_ProcessName(&pProcName);
在控制台应用程序中,此调用可以很好地执行并返回正确的值.但是,当我在MFC OnInitDialog()中调用此功能时,它将失败并提示一个断言.
当我调试代码时,我得到以下失败信息:
In console application, this call can be executed well and return the right value. But when i call this fucntion in MFC OnInitDialog(), it will fail and prompt a assert.
When i debug into the code, i''ve got the following failure info:
!heap -s -v
Details:==============================
Error address: 0041185c
Heap handle: 003a0000
Error type heap_failure_invalid_argument (9)
Stack trace:
772cddff: ntdll!RtlFreeHeap+0x00000064
75ad6e6a: ole32!CRetailMalloc_Free+0x0000001c
75ad6f54: ole32!CoTaskMemFree+0x00000013
758e154c: RPCRT4!NdrFreeTypeMemory+0x00000046
758d24a9: RPCRT4!NdrPointerFree+0x000000a8
7594555e: RPCRT4!NdrpFreeParams+0x00000145
75945445: RPCRT4!NdrStubCall2+0x000004e0
75bbaec1: ole32!CStdStubBuffer_Invoke+0x0000003c
75bbd876: ole32!SyncStubInvoke+0x0000003c
75bbddd0: ole32!StubInvoke+0x000000b9
75ad8a43: ole32!CCtxComChnl::ContextInvoke+0x000000fa
75ad8938: ole32!MTAInvoke+0x0000001a
75bba44c: ole32!AppInvoke+0x000000ab
75bbdb41: ole32!ComInvokeWithLockAndIPID+0x00000372
75bbe1fd: ole32!ComInvoke+0x000000c5
75ad9367: ole32!ThreadDispatch+0x00000023
NtGlobalFlag enables following debugging aids for new heaps: tail checking
free checking
validate parameters
Index Address Name Debugging options enabled
1: 003a0000 tail checking free checking validate parameters
2: 00010000 tail checking free checking validate parameters
3: 00670000 tail checking free checking validate parameters
4: 00650000 tail checking free checking validate parameters
5: 005f0000 tail checking free checking validate parameters
6: 02500000 tail checking free checking validate parameters
7: 024d0000 tail checking free checking validate parameters
8: 03e30000 tail checking free checking validate parameters
9: 03d60000 tail checking free checking validate parameters
10: 024f0000 tail checking free checking validate parameters
And the !analyze -v ====================================
FAULTING_IP:
ntdll!RtlReportCriticalFailure+29
773137dd cc int 3
EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 773137dd (ntdll!RtlReportCriticalFailure+0x00000029)
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 3
Parameter[0]: 00000000
Parameter[1]: 84d79d48
Parameter[2]: 056cee5d
FAULTING_THREAD: 00000be4
PROCESS_NAME: TestCOMListView.exe
ERROR_CODE: (NTSTATUS) 0x80000003 - {EXCEPTION} Breakpoint A breakpoint has been reached.
EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are invalid
EXCEPTION_PARAMETER1: 00000000
EXCEPTION_PARAMETER2: 84d79d48
EXCEPTION_PARAMETER3: 056cee5d
MOD_LIST: <ANALYSIS/>
NTGLOBALFLAG: 70
APPLICATION_VERIFIER_FLAGS: 0
LAST_CONTROL_TRANSFER: from 7731473b to 773137dd
DEFAULT_BUCKET_ID: ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument
PRIMARY_PROBLEM_CLASS: ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument
BUGCHECK_STR: APPLICATION_FAULT_ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument
STACK_TEXT:
056cf128 7731473b c0000374 7732cdd8 056cf16c ntdll!RtlReportCriticalFailure+0x29
056cf138 7731481b 00000002 723f5340 00000000 ntdll!RtlpReportHeapFailure+0x21
056cf16c 772cddff 00000009 003a0000 0041185c ntdll!RtlpLogHeapFailure+0xa1
056cf19c 75ad6e6a 003a0000 00000000 0041185c ntdll!RtlFreeHeap+0x64
056cf1b0 75ad6f54 75bc66bc 0041185c 056cf1dc ole32!CRetailMalloc_Free+0x1c
056cf1c0 758e154c 0041185c 758d24d3 637733e8 ole32!CoTaskMemFree+0x13
056cf1c8 758d24d3 637733e8 637733ec 056cf24c RPCRT4!NdrFreeTypeMemory+0x46
056cf1dc 758d24a9 0041185c 0041185c 637733ec RPCRT4!NdrPointerFree+0xf3
056cf1fc 7594555e 0041185c 056cf428 007733e8 RPCRT4!NdrPointerFree+0xa8
056cf220 75945445 056cf428 00000002 6377318a RPCRT4!NdrpFreeParams+0x145
056cf234 759453ff e1818bfa 00412560 0040f100 RPCRT4!NdrStubCall2+0x4e0
056cf630 75bbaec1 00412560 00402fa8 0040f100 RPCRT4!NdrStubCall2+0x415
056cf678 75bbd876 00412560 0040f100 00402fa8 ole32!CStdStubBuffer_Invoke+0x3c
056cf6c0 75bbddd0 0040f100 0041325c 00411a48 ole32!SyncStubInvoke+0x3c
056cf70c 75ad8a43 0040f100 00412160 00412560 ole32!StubInvoke+0xb9
056cf7e8 75ad8938 00402fa8 00000000 00412560 ole32!CCtxComChnl::ContextInvoke+0xfa
056cf804 75bba44c 0040f100 00000001 00412560 ole32!MTAInvoke+0x1a
056cf834 75bbdb41 d0908070 00402fa8 00412560 ole32!AppInvoke+0xab
056cf914 75bbe1fd 0040f0a8 00403b78 00000000 ole32!ComInvokeWithLockAndIPID+0x372
056cf93c 75ad9367 0040f0a8 76fdc2b0 0040f258 ole32!ComInvoke+0xc5
056cf950 75aacd48 0040f0a8 00000000 0040f258 ole32!ThreadDispatch+0x23
056cf96c 75aad87a 00000000 00000000 056cf988 ole32!CRpcThread::WorkerLoop+0x26
056cf97c 76fded6c 0040f258 056cf9c8 772b377b ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x16
056cf988 772b377b 0040f258 723f5be4 00000000 kernel32!BaseThreadInitThunk+0xe
056cf9c8 772b374e 75aad864 0040f258 00000000 ntdll!__RtlUserThreadStart+0x70
056cf9e0 00000000 75aad864 0040f258 00000000 ntdll!_RtlUserThreadStart+0x1b
STACK_COMMAND: .cxr 00000000 ; kb ; !heap ; dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; ~7s ; kb
FOLLOWUP_IP:
RPCRT4!NdrFreeTypeMemory+46
758e154c c3 ret
SYMBOL_STACK_INDEX: 6
SYMBOL_NAME: rpcrt4!NdrFreeTypeMemory+46
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: RPCRT4
IMAGE_NAME: RPCRT4.dll
DEBUG_FLR_IMAGE_TIMESTAMP: 4ce7b9a2
FAILURE_BUCKET_ID: ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument_80000003_RPCRT4.dll!NdrFreeTypeMemory
BUCKET_ID: APPLICATION_FAULT_ACTIONABLE_HEAP_CORRUPTION_heap_failure_invalid_argument_rpcrt4!NdrFreeTypeMemory+46
WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/TestCOMListView_exe/1_0_0_1/4f56cbbc/ntdll_dll/6_1_7601_17725/4ec49b60/80000003/000c37dd.htm?Retriage=1
Followup: MachineOwner
---------
Call stack=================================
0:007> k
ChildEBP RetAddr
056cf128 7731473b ntdll!RtlReportCriticalFailure+0x29
056cf138 7731481b ntdll!RtlpReportHeapFailure+0x21
056cf16c 772cddff ntdll!RtlpLogHeapFailure+0xa1
056cf19c 75ad6e6a ntdll!RtlFreeHeap+0x64
056cf1b0 75ad6f54 ole32!CRetailMalloc_Free+0x1c
056cf1c0 758e154c ole32!CoTaskMemFree+0x13
056cf1c8 758d24d3 RPCRT4!NdrFreeTypeMemory+0x46
056cf1dc 758d24a9 RPCRT4!NdrPointerFree+0xf3
056cf1fc 7594555e RPCRT4!NdrPointerFree+0xa8
056cf220 75945445 RPCRT4!NdrpFreeParams+0x145
056cf234 759453ff RPCRT4!NdrStubCall2+0x4e0
056cf630 75bbaec1 RPCRT4!NdrStubCall2+0x415
056cf678 75bbd876 ole32!CStdStubBuffer_Invoke+0x3c
056cf6c0 75bbddd0 ole32!SyncStubInvoke+0x3c
056cf70c 75ad8a43 ole32!StubInvoke+0xb9
056cf7e8 75ad8938 ole32!CCtxComChnl::ContextInvoke+0xfa
056cf804 75bba44c ole32!MTAInvoke+0x1a
056cf834 75bbdb41 ole32!AppInvoke+0xab
056cf914 75bbe1fd ole32!ComInvokeWithLockAndIPID+0x372
056cf93c 75ad9367 ole32!ComInvoke+0xc5
056cf950 75aacd48 ole32!ThreadDispatch+0x23
056cf96c 75aad87a ole32!CRpcThread::WorkerLoop+0x26
056cf97c 76fded6c ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x16
056cf988 772b377b kernel32!BaseThreadInitThunk+0xe
056cf9c8 772b374e ntdll!__RtlUserThreadStart+0x70
056cf9e0 00000000 ntdll!_RtlUserThreadStart+0x1b
推荐答案
不要在客户端中分配pProcName
您正在该指针之上执行SysAlloc
don''t allocate pProcName in the client
You''re doing a SysAlloc on top of that pointer
将此参数更改为该propget函数的BSTR *即可解决此问题.但不清楚为什么会这样.....
COM做任何发布工作都不同吗?
Change the parameter to BSTR* of this propget function can resolvs the issue. but not clear why this happens.....
Is COM doing anything release works differently?
STDMETHODIMP CExProcessInfo::get_m_ProcessName(BSTR* pVal)
{
// TODO: Add your implementation code here
if(m_pProcessName == NULL)
*pVal = ::SysAllocString(L"");
else
{
*pVal = ::SysAllocString(m_pProcessName);
}
return S_OK;
}
当我搜索MSDN时,发现BSTR的评论是:
如果将简单的Unicode字符串作为期望BSTR的COM函数的参数传递,则COM函数将失败.
因此,在使用SysAllocString时,应将pVal作为带有长度前缀的BSTR返回.否则,内存将无法正确回收并导致堆崩溃.
参考链接: http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms221069(v = vs.85).aspx [
As i searched MSDN, found that BSTR''s remark:
If you pass a simple Unicode string as an argument to a COM function that is expecting a BSTR, the COM function will fail.
So when using SysAllocString, the pVal should be returned as a BSTR which with length prefix. If not, the memory will not be recycled properly and cause the heap crash.
Reference Link: http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069(v=vs.85).aspx[^]
这篇关于导致堆失败的原因的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!