Windows 10下的malloc

SDK版本:10.0.18362.0

msvc在debug模式中会在程序申请堆内存时作出一定处理,为了探究内存结构,写出如下调试程序:

void *p[20];
for (int i=0;i<20;i++) {
    p[i] = malloc(0x1000);
}

以下为对内存的分析,截取了两块堆内存中间的区域作为例子。

0x0000022B2D5C32C0  cd cd cd cd cd cd cd cd  ???????? // 数据区
0x0000022B2D5C32C8  cd cd cd cd cd cd cd cd  ???????? // 数据区
0x0000022B2D5C32D0  fd fd fd fd 00 00 00 00  ????.... // unsigned char _another_gap[no_mans_land_size] + pad
0x0000022B2D5C32D8  dc 60 39 b0 c0 95 00 0c  ?`9???.. // ?
以下为新的malloc(Heapmalloc)分配的块,大小0x1038,其中cookie为56B
0x0000022B2D5C32E0  a0 22 5c 2d 2b 02 00 00  ?"\-+... // _CrtMemBlockHeader* _block_header_next
0x0000022B2D5C32E8  20 43 5c 2d 2b 02 00 00   C\-+... // _CrtMemBlockHeader* _block_header_prev
0x0000022B2D5C32F0  00 00 00 00 00 00 00 00  ........ // char const*         _file_name
0x0000022B2D5C32F8  00 00 00 00 01 00 00 00  ........ // int _line_number + int _block_use
0x0000022B2D5C3300  00 10 00 00 00 00 00 00  ........ // size_t _data_size
0x0000022B2D5C3308  a5 00 00 00 fd fd fd fd  ?...???? // long _request_number + unsigned char _gap[no_mans_land_size]
0x0000022B2D5C3310  cd cd cd cd cd cd cd cd  ???????? // 数据区
0x0000022B2D5C3318  cd cd cd cd cd cd cd cd  ???????? // 数据区
调试模式下,malloc转而调用_malloc_dbg
in malloc.cpp, line 23
return _malloc_dbg(size, _NORMAL_BLOCK, nullptr, 0);
                         1              0        0  
调整大小以容纳调试头
in debug_heap.cpp, line 357
size_t const block_size{sizeof(_CrtMemBlockHeader) + size + no_mans_land_size};
             0x1034     0x30                         0x100  0x4
    in line 65: static size_t const no_mans_land_size = 4;
    in line 83:
// For diagnostic purpose, blocks are allocated in the debug heap with extra
// information and stored in a doubly-linked list.  This makes all blocks
// registered with how big they are, when they were allocated, and what they are
// used for.
struct _CrtMemBlockHeader
{
    _CrtMemBlockHeader* _block_header_next;
    _CrtMemBlockHeader* _block_header_prev;
    char const*         _file_name;
    int                 _line_number;

    int                 _block_use;
    size_t              _data_size;

    long                _request_number;
    unsigned char       _gap[no_mans_land_size];

    // Followed by:
    // unsigned char    _data[_data_size];
    // unsigned char    _another_gap[no_mans_land_size];
};
注意:in vcruntime.h, line 193: typedef unsigned __int64 size_t;

调用win32 api HeapAlloc 完成内存获取
in debug_heap.cpp, line 359:
    _CrtMemBlockHeader* const header{static_cast<_CrtMemBlockHeader*>(HeapAlloc(__acrt_heap, 0, block_size))};

最后写入调试头,将gap填充为no_mans_land_fill(0xfd),将数据区填充为clean_land_fill(0xcd),完成malloc过程。

调用栈:

ucrtbased.dll!malloc(unsigned __int64 size=4096) 行 27
 ucrtbased.dll!_malloc_dbg(unsigned __int64 size=4096, int block_use=1, const char * file_name=0x0000000000000000, int line_number=0) 行 496
  ucrtbased.dll!heap_alloc_dbg(const unsigned __int64 size=4096, const int block_use=1, const char * const file_name=0x0000000000000000, const int line_number=0) 行 450
   ucrtbased.dll!heap_alloc_dbg_internal(const unsigned __int64 size=4096, const int block_use=1, const char * const file_name=0x0000000000000000, const int line_number=0) 行 357
    ntdll.dll!RtlAllocateHeap() 注:Win32 Api
     ntdll.dll!RtlpAllocateHeap()
      ntdll.dll!RtlpExtendHeap()
       ntdll.dll!RtlpFindAndCommitPages()
        ntdll.dll!RtlpFindUCREntry()
        ntdll.dll!RtlpGetHeapProtection()
         ntdll.dll!RtlpHpHeapValidateProtection()
        ntdll.dll!RtlpHpHeapCheckCommitLimit()
        ntdll.dll!NtAllocateVirtualMemory()
         a syscall
        ntdll.dll!RtlGetCurrentServiceSessionId()
        ntdll.dll!RtlpRemoveUCRBlock()
         ntdll.dll!RtlpUpdateUCRIndexRemove()
        ntdll.dll!RtlpCreateUCREntry()
         ntdll.dll!RtlpInsertUCRBlock()
          ntdll.dll!RtlpFindUCREntry()
         ntdll.dll!RtlpUpdateUCRIndexInsert()
        ntdll.dll!RtlGetCurrentServiceSessionId()
        ntdll.dll!RtlGetCurrentServiceSessionId()
       ntdll.dll!RtlpCoalesceFreeBlocks()
        ntdll.dll!RtlpHeapRemoveListEntry()
       ntdll.dll!RtlpInsertFreeBlock()
        ntdll.dll!RtlpFindEntry()
         ntdll.dll!RtlpHeapFindListLookupEntry()
        ntdll.dll!RtlpHeapAddListEntry()
      ntdll.dll!RtlpHeapRemoveListEntry()
       ntdll.dll!RtlpInsertFreeBlock()
        ntdll.dll!RtlpFindEntry()
        ntdll.dll!RtlpHeapAddListEntry()
      ntdll.dll!RtlpHeapRemoveListEntry()
      ntdll.dll!RtlLeaveCriticalSection()
    3*memset()
点赞