-
-
[原创]VC++6调试状态下的堆结构
-
发表于:
2024-8-28 09:01
4688
-
C语言标准对堆内存的申请提供了三个函数:
释放堆内存提供一个函数:
C标准函数落地到具体的操作系统,需要系统调用,Windows提供了如下5个系统调用:
在VC++平台,除了C标准库函数,还提供了相对应的调试版函数:
先准备一段C代码:
在VC++6中,main函数是由mainCRTStartup函数调用的,可以通过栈帧窗口定位到该函数,然后在堆初始化处打一个断点:
步入_heap_init方法,这里调用了系统调用HeapCreate:
单步往下执行,可以看到有调用HeapDestroy的地方,不过该分支并没有执行到:
在main函数中调用malloc的地方打断点:
层层步入:
最终执行到这里,调用了HeapAlloc系统调用:
接下来跟进calloc函数:
步入_calloc_dbg,这里将入参nSize和nNum相乘并将乘积赋值给nSize,并且再用nSize调用_malloc_dbg:
继续跟进的话,发现最终也调用了HeapAlloc:
再跟进realloc函数:
最终调用了HeapReAlloc:
最后跟进free函数:
最终调用了HeapFree:
在main函数返回后,会调用exit函数结束进程,exit最终会跟进到一个ExitProcess调用,里面会调用HeapDestroy销毁堆,但由于这是一个系统函数,所以无法步入。
总结:
进程启动时调用HeapCreate创建堆;
malloc底层调用了HeapAlloc;
calloc先计算num*size,再调用malloc;
realloc底层调用了HeapReAlloc;
free底层调用了HeapFree;
进程退出时,调用HeapDestroy。
VC++平台提供的调试版函数可以在堆内存中添加更多附加信息,方便调试,所以我们在代码中定义几个宏:
这样在使用C标准函数时会替换为调试版函数,以_malloc_dbg为例解释入参含义:
size 申请堆内存的字节数
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-8-28 09:20
被米龙·0xFFFE编辑
,原因: