-
-
[原创]VC++6调试状态下的堆结构
-
发表于:
2024-8-28 09:01
7525
-
C语言标准对堆内存的申请提供了三个函数:
1 2 3 | void * malloc ( size_t size );
void * calloc ( size_t num, size_t size );
void * realloc ( void *memblock, size_t size );
|
释放堆内存提供一个函数:
1 | void free ( void *memblock );
|
C标准函数落地到具体的操作系统,需要系统调用,Windows提供了如下5个系统调用:
1 2 3 4 5 | HANDLE HeapCreate( DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize);
LPVOID HeapAlloc( HANDLE hHeap, DWORD dwFlags, DWORD dwBytes);
LPVOID HeapReAlloc( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, DWORD dwBytes);
BOOL HeapFree( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
BOOL HeapDestroy( HANDLE hHeap);
|
在VC++平台,除了C标准库函数,还提供了相对应的调试版函数:
1 2 3 | void *_malloc_dbg( size_t size, int blockType, const char *filename, int linenumber );
void *_calloc_dbg( size_t num, size_t size, int blockType, const char *filename, int linenumber );
void *_realloc_dbg( void *userData, size_t newSize, int blockType, const char *filename, int linenumber );
|
先准备一段C代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crtdbg.h>
int main( int argc, char *argv[], char *env[])
{
char *psz = ( char *) malloc (5);
strcpy (psz, "xxyy" );
int *pn = ( int *) calloc ( sizeof ( int ), 3);
*pn = 999;
psz = ( char *) realloc (psz, 2);
psz = ( char *) realloc (psz, 20);
free (pn);
pn = ( int *) malloc ( sizeof ( int ));
*pn = 666;
free (pn);
free (psz);
return 0;
}</crtdbg.h></string.h></stdlib.h></stdio.h>
|
在VC++6中,main函数是由mainCRTStartup函数调用的,可以通过栈帧窗口定位到该函数,然后在堆初始化处打一个断点:

步入_heap_init方法,这里调用了系统调用HeapCreate:

单步往下执行,可以看到有调用HeapDestroy的地方,不过该分支并没有执行到:

在main函数中调用malloc的地方打断点:

层层步入:



最终执行到这里,调用了HeapAlloc系统调用:

接下来跟进calloc函数:

步入_calloc_dbg,这里将入参nSize和nNum相乘并将乘积赋值给nSize,并且再用nSize调用_malloc_dbg:

继续跟进的话,发现最终也调用了HeapAlloc:

再跟进realloc函数:



最终调用了HeapReAlloc:

最后跟进free函数:


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2024-8-28 09:20
被米龙·0xFFFE编辑
,原因: