一、crt new实现方法
new——>全局operator new(afxmem.h)——>_malloc_dbg(crtdbg.h)——>_heap_alloc_dbg_impl(dbgheap.h
此处生成了debug头,mfc内存泄露检测就是使用此cookie)——>_heap_alloc_base(malloc.h)
_heap_alloc_base代码如下:
_forceinline void * __cdecl _heap_alloc (size_t size) { if (_crtheap == 0) { _FF_MSGBANNER(); /* write run-time error banner */ _NMSG_WRITE(_RT_CRT_NOTINIT); /* write message */ __crtExitProcess(255); /* normally _exit(255) */ } if (__active_heap == __SYSTEM_HEAP) { return HeapAlloc(_crtheap, 0, size ? size : 1); } else if ( __active_heap == __V6_HEAP ) { if (pvReturn = V6_HeapAlloc(size)) { return pvReturn; } } #ifdef CRTDLL else if ( __active_heap == __V5_HEAP ) { if (pvReturn = V5_HeapAlloc(size)) { return pvReturn; } } #endif /* CRTDLL */ if (size == 0) size = 1; size = (size + BYTES_PER_PARA - 1) & ~(BYTES_PER_PARA - 1); return HeapAlloc(_crtheap, 0, size); }
其中_crtheap在Dll附加到进程调用__DllMainCRTStartup——>_CRT_INIT——>_heap_init代码如下:
int __cdecl _heap_init ( int mtflag ) { #if defined _M_AMD64 || defined _M_IA64 // HEAP_NO_SERIALIZE is incompatible with the LFH heap mtflag = 1; #endif /* defined _M_AMD64 || defined _M_IA64 */ // Initialize the "big-block" heap first. if ( (_crtheap = HeapCreate( mtflag ? 0 : HEAP_NO_SERIALIZE, BYTES_PER_PAGE, 0 )) == NULL ) return 0; #ifndef _WIN64 // Pick a heap, any heap __active_heap = __heap_select();//默认为system_heap if ( __active_heap == __V6_HEAP ) { // Initialize the small-block heap if (__sbh_heap_init(MAX_ALLOC_DATA_SIZE) == 0) { HeapDestroy(_crtheap); _crtheap=NULL; return 0; } } #ifdef CRTDLL else if ( __active_heap == __V5_HEAP ) { if ( __old_sbh_new_region() == NULL ) { HeapDestroy( _crtheap ); _crtheap=NULL; return 0; } } #endif /* CRTDLL */ #elif defined _M_AMD64 || defined _M_IA64 { // Enable the Low Fragmentation Heap for AMD64 and IA64 by default // It's the 8 byte overhead heap, and has generally better // performance charateristics than the 16 byte overhead heap, // particularly for apps that perform lots of small allocations ULONG HeapType = 2; HeapSetInformation(_crtheap, HeapCompatibilityInformation, &HeapType, sizeof(HeapType)); } #endif /* defined _M_AMD64 || defined _M_IA64 */ return 1; }
由1可知,当dll以静态链接的方式(MT)使用时,dll中得string和动态内存是在dll的堆中分配的。所以必须在dll中释放。当以动态链接crt时,所有dll都共用crt dll(MD),分配和释放都在同一个堆上。
备注:string有默认16字节的小内存,当字符串大小小于16字节时不会动态分配内存。