用Win32SDK编程可以有多种方法分配内存
1.GlobalAlloc
2.HeapAlloc
3.LocalAlloc
4.VirtualAlloc(Ex)
以及标准C/C++中的
5.malloc
6.calloc
7.new
用不同的方法申请了64KB大小空间,以下是返回的地址值(WindowsXPsp2):
LocalAlloc: 00143060
GlobalAlloc: 00143060
HeapAlloc: 00143060
VirtualAlloc: 00390000
malloc: 00410048
new: 00410048
可见LocalAlloc和GlobalAlloc的地址和堆分配是一样的,
MSDN也写着前两个函数只是为兼容16位版本而保留的,所以不建议再使用了.
VirtualAlloc分配比较复杂,可以设置分配内存的属性.
malloc和new的结果相同.
这样就共有3种结果了.
我简单的说几句。
调用关系如下 new->malloc->HeapAlloc->VirtualAlloc->驱动程序的_PageAlloc。
上面的调用关系是一般的WIN32编译器的调用顺序。
其中HeapAlloc已经实现了malloc的那些小块内存管理,以Heap开头的有一系列函数,你会发现它与malloc/free等可以对应起来。
但是Borland和VC编译器稍有不同,它们选择了自己实现了malloc,而不是直接对Heap*函数做了简单包装。
当然,有些C++编译器new并不是先调用malloc,然后调用构造函数,但总的来说,内存的调用顺序如上。
LocalAlloc和GlobalAlloc是遗留函数。
在WindowsXP中跟踪了一下:
malloc(msvcrt.malloc)和new(msvcrt.??2@YAPAXI@Z)的函数体大部分(主要是核心部分)是相同的,所以结果分配也是相同的.
这两个函数都是调用kernel32.HeapAlloc实现的.
以下是我跟踪出来的详细调用关系:
msvcrt.malloc => kernel32.HeapAlloc(ntdll.RtlAllocateHeap)
msvcrt.??2@YAPAXI@Z => kernel32.HeapAlloc(ntdll.RtlAllocateHeap)
kernel32.LocalAlloc => ntdll.RtlAllocateHeap
kernel32.GlobleAlloc => ntdll.RtlAllocateHeap
kernel32.HeapAlloc == ntdll.RtlAllocateHeap
kernel32.VirtualAlloc => kernel32.VirtualAllocEx
kernel32.VirtualAllocEx=> ntdll.NtAllocateVirtualMemory
ntdll.RtlAllocateHeap => ntdll.NtAllocateVirtualMemory
ntdll.NtAllocateVirtualMemory => ntdll.KiFastSystemCall
ntdll.KiFastSystemCall => sysenter指令 (0F34)
(注意kernel32中实际没有HeapAlloc的入口地址,而是直接映射到ntdll.RtlAllocateHeap的入口)