CRT堆

实验环境:win764位旗舰版、VS2010旗舰版

	每个进程都有一个默认堆,在进程初始化的时候会创建这个默认堆,可以通过GetProcessHeap()获取默认堆的句柄。使用CRT时,也会有一个CRT堆,VS项目属性 ~ C/C++ ~ 代码生成 ~ 运行库,如果选择多线程DLL,则CRT堆初始化在DLL中,如果选择多线程,则会在进入_tmain函数之前。

运行库连接方式设置:

 

CRT堆初始化:

位于VS目录Microsoft Visual Studio 10.0\VC\crt\src\heapinit.c文件中有一个_heap_init函数,可以设置断点查看CRT堆初始化过程。

int __cdecl _heap_init (void)
{
        ULONG HeapType = 2;

        //  Initialize the "big-block" heap first.
        if ( (_crtheap = HeapCreate(0, BYTES_PER_PAGE, 0)) == NULL )
            return 0;

#ifdef _WIN64
        // Enable the Low Fragmentation Heap by default on Windows XP and
        // Windows Server 2003.  It's the 8 byte overhead heap, and has
        // generally better performance charateristics than standard heap,
        // particularly for apps that perform lots of small allocations.

        if (LOBYTE(GetVersion()) < 6)
        {
            HeapSetInformation(_crtheap, HeapCompatibilityInformation,
                               &HeapType, sizeof(HeapType));
        }
#endif  /* _WIN64 */
        return 1;
}

注意:这里调用HeapCreate函数的第一个参数使用0,而没有使用HEAP_NO_SERIALIZE标志,则表示对堆的访问时独占的,即默认情况下使用new和delete是线程安全的。

 

c++使用new是在CRT堆上分配内存:

位于VS目录Microsoft Visual Studio 10.0\VC\crt\src\malloc.c文件中有一个_heap_alloc函数

__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) */
    }

    return HeapAlloc(_crtheap, 0, size ? size : 1);
}

 

	经常听到高手说,最好不要跨模块new和delete,否则将会出现严重的错误(堆被破坏)。例如在DLL中使用new分配一块内存,让后在EXE中使用delete释放这块内存,有可能堆会被破坏,原因是,如果EXE和DLL都是用静态库的方式链接运行时库,此时EXE和DLL各自将有一个CRT堆,在一个堆上分配内存,让后再另一个堆上释放内存是肯定会发生错误的。如果EXE和DLL都是用动态库的方式链接运行时库,他们使用的是同一个CRT堆,则不会发错误。

posted on 2014-12-14 15:35  dchao  阅读(1437)  评论(0编辑  收藏  举报

导航