Re: 请教一个关于堆的问题
C/C++本地代码调试
请教一个关于堆的问题
zhaohui2
2014-12-03, 19:36 下午
学习堆的时候遇到一个很奇怪的问题
debug版本下调用HeapSize()会引发异常(Release 版本就不会).
这个是引发异常的代码
PCHAR str = (PCHAR)malloc(10);
HeapSize(GetProcessHeap(),0,str);
用windbg调试,给出如下的信息:
0:000> g
HEAP[EnumProcess.exe]: Invalid address specified to RtlSizeHeap( 00A30000, 00A3CD80 )
(a7c.16a4): Break instruction exception - code 80000003 (first chance)
eax=7ee6f000 ebx=00a3cd78 ecx=00a3cd78 edx=0000003f esi=00a30000 edi=00a3cd80
eip=773e05be esp=0098f964 ebp=0098f97c iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
ntdll!RtlpBreakPointHeap+0x19:
773e05be cc int 3
请问张老师,为什么会出现这样的情况
Re: 请教一个关于堆的问题
格蠹老雷
2014-12-04, 01:30 上午
因为malloc只分了10个字节,可能是从CRT的LBH堆上分配的,所以把这个地址给Win32堆就是无效堆地址了,Debug版通过INT3报告了,release版本可能静默失败了。
把分配大小改大,比如4000,试一下
Re: 请教一个关于堆的问题
zhaohui2
2014-12-04, 22:10 下午
用4000试了,还是同样的异常
Re: 请教一个关于堆的问题
CutlerMao
2015-09-20, 16:39 下午
Release模式下:
malloc最终会调用HeapAlloc(实际上是:RtlAllocateHeap),这种内存分配条件下,我们得到的UserPtr前面8个字节会放置一个叫做_HEAP_ENTRY的结构,这里面会描述UserPtr所指向的空间的大小。
在Release模式下,malloc和直接调用HeapAlloc,均是以上行为。
Debug模式下(与Release稍有不同):
malloc从CRT堆中分配内存,CRT堆在Debug模式下有自己的一套,UserPtr前面20个字节是一个叫做_CrtMemBlockHeader的结构,而不是_HEAP_ENTRY的结构。问题来了~ HeapSize(实际上是:RtlSizeHeap)的调用会假定你所给出的UserPtr前面的8个字节是_HEAP_ENTRY,但很不幸,你给的UserPtr前面是一个_CrtMemBlockHeader结构。HeapSize并不完全相信你给的参数的合法性,所以其实现内部会如下这样:
if (DEBUG_HEAP( Flags )) {
return RtlDebugSizeHeap( HeapHandle, Flags, BaseAddress );
}
也就是说,如果发现所使用的堆有调试标记,则检查你给的参数的合法性,结果检查没有通过,直接int 3断下来,给你一次改成错误的机会。
Re: 请教一个关于堆的问题
chena_cpp
2015-10-29, 12:58 下午
好像分配小块内存并不会每次都创建一个_HEAP_ENTRY,我new了几万次,然后用windbg看,_HEAP_ENTRY只有几百个。
Re: 请教一个关于堆的问题
irp
2015-11-01, 14:50 下午
GetProcessHeap() => process default heap
malloc() => crt heap (static or dll), crt都是private heap, 不是process default heap.
你传给HeapSize()的是无效堆句柄,当然会出错。release 关掉了报错,debug下raiseexception是帮助调试的手段。