malloc()
可以通过扩展堆或通过mmap()
足够大的内存块来分配内存。它使用哪一个取决于您要求的大小和几个mallopt()
选项。
如果它使用“真实”堆部分,它通常位于虚拟内存区域的开头,它可以增长到到达下一个分配的内存块的位置,该内存块距离开头很远。
如果它使用mmap()
,则取决于是否有可用的连续地址空间。
/proc/<PID>/maps
是查找进程地址空间情况的一个很好的查询点。
我刚刚用 Python 和 ctypes 测试了我的 64 位服务器:
import ctypes
import ctypes.util
m=ctypes.CDLL(ctypes.util.find_library("c")).malloc
m.argtypes=(ctypes.c_uint64,)
m.restype = ctypes.c_uint64
现在我有了m
,它作为对 libcmalloc()
函数的调用。
现在我可以做
>>> hex(m(2700000000))
'0x7f1345e3b010L'
>>> hex(m(2700000000))
'0x7f12a4f4f010L'
>>> hex(m(2700000000))
'0x7f1204063010L'
>>> hex(m(2700000000))
'0x7f1163177010L'
>>> hex(m(2700000000))
'0x7f10c228b010L'
>>> hex(m(2700000000))
'0x7f102139f010L'
>>> hex(m(2700000000))
'0x7f0f804b3010L'
但由于任何原因我不能做
>>> hex(m(2900000000))
'0x0L'
因为它分别返回 0。一个空指针。
现在做
print open("/proc/self/maps").read()
向我显示所述文件的行;在某处
7f0ed8000000-7f0ed8021000 rw-p 00000000 00:00 0
7f0ed8021000-7f0edc000000 ---p 00000000 00:00 0
7f0edf5c7000-7f13e6d27000 rw-p 00000000 00:00 0
我得到了我的分配。
但是,如果我这样做
>>> hex(m(1))
'0x1f07320L'
>>> hex(m(1))
'0x1f0c0e0L'
>>> hex(m(1))
'0x1f02d50L'
>>> hex(m(1))
'0x1f02d70L'
>>> hex(m(1))
'0x1ef94f0L'
>>> hex(m(1))
'0x1eb7b20L'
>>> hex(m(1))
'0x1efb700L'
>>> hex(m(270))
'0x1f162a0L'
>>> hex(m(270))
'0x1f163c0L'
>>> hex(m(270))
'0x1f164e0L'
>>> hex(m(270))
'0x1f16600L'
内存地址来自
>>> print open("/proc/self/maps").read()
[...]
01d2e000-01f2b000 rw-p 00000000 00:00 0 [heap]
[...]
指定的堆。
请注意,虽然我可以分配此内存,但使用它都会造成伤害,因为我的进程可能会被著名的 OOM 杀手杀死。