当前位置:  开发笔记 > 运维 > 正文

为什么malloc(1)提供多个页面大小?

如何解决《为什么malloc(1)提供多个页面大小?》经验,为你挑选了1个好方法。

我已经尝试在我的机器上使用sbrk(1)然后故意写出测试页面大小,这是4096字节.但是当我调用malloc(1)时,我在访问135152字节后获得了SEGV,这超过了一个页面大小.我知道malloc是库函数,它依赖于实现,但考虑到它最终会调用sbrk,为什么它会给出多个页面大小.谁能告诉我它的内部工作?

我的操作系统是ubuntu 14.04,我的架构是x86

更新:现在我想知道是不是因为malloc将地址返回到足以容纳我的数据的空闲列表块.但是该地址可能位于堆的中间,因此我可以继续写入,直到达到堆的上限.



1> P.P...:

较旧malloc()的UNIX实现sbrk()/ brk()系统调用.但是现在,实现使用mmap()sbrk().在malloc()glibc的实施(这可能是你在你的Ubuntu 14.04使用的)同时使用sbrk(),并mmap()与选择使用哪一个,当你要求通常取决于分配请求,glibc哪个动态做的大小来分配.

对于小分配,glibc使用sbrk()它并使用更大的分配mmap().宏M_MMAP_THRESHOLD用于决定这一点.目前,它的默认值设置为128K.这解释了为什么你的代码设法分配135152字节,因为它大约是~128K.即使您只请求了1个字节,您的实现也会分配128K以进行有效的内存分配.因此,在超过此限制之前,不会发生段错误.

您可以通过更改默认参数M_MAP_THRESHOLD来使用mallopt().

M_MMAP_THRESHOLD

对于由M_MMAP_THRESHOLD分配大于或等于指定的(以字节计)的限制时,不能满足从空闲列表,存储器分配函数采用MMAP(2),而不是使用SBRK增加程序中断(2).

使用mmap(2)分配内存具有明显的优势,即分配的内存块总是可以独立地释放回系统.(与此相反,堆可以仅当存储器在顶部端释放修整.).另一方面,也有一些缺点的用途MMAP(2)的:解除分配的空间没有被放置在空闲列表进行再利用上以后的分配; 内存可能会被浪费,因为mmap(2)分配必须是页面对齐的; 并且内核必须执行将通过mmap(2)分配的内存清零的昂贵任务.平衡这些因素会导致M_MMAP_THRESHOLD参数的默认设置为128*1024.

此参数的下限为0. 32位系统上的上限为DEFAULT_MMAP_THRESHOLD_MAX:512*1024或64位系统上的上限为4*1024*1024*sizeof(long).

注意:现在,glibc默认使用动态mmap阈值.阈值的初始值是128×1024,但是,当超过电流阈值且小于或等于DEFAULT_MMAP_THRESHOLD_MAX被释放的块,则阈值被向上调整到释放的块的大小.当动态mmap阈值处于有效状态时,修剪堆的阈值也会动态调整为动态mmap阈值的两倍.如果设置了M_TRIM_THRESHOLD,M_TOP_PAD,M_MMAP_THRESHOLD或M_MMAP_MAX参数中的任何一个,则禁用动态调整mmap阈值.

例如,如果你这样做:

#include

mallopt(M_MMAP_THRESHOLD, 0);

在打电话之前malloc(),你可能会看到不同的限制.其中大部分都是实现细节,而C标准表示,在您的进程不拥有的内存中写入未定义的行为.所以冒着风险 - 否则,恶魔可能会飞出你的鼻子 ;-)

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有