crt new实现方法,Dll导出函数返回string和动态内存陷阱

一、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;
}

二、Dll导出函数返回string和动态内存陷阱

由1可知,当dll以静态链接的方式(MT)使用时,dll中得string和动态内存是在dll的堆中分配的。所以必须在dll中释放。当以动态链接crt时,所有dll都共用crt dll(MD),分配和释放都在同一个堆上。

备注:string有默认16字节的小内存,当字符串大小小于16字节时不会动态分配内存。

你可能感兴趣的:(crt new实现方法,Dll导出函数返回string和动态内存陷阱)