And*_*sne 40 c malloc memory-management
当我们使用malloc()分配内存时,我们应该给出两个幂的大小吗?或者我们只是给出我们需要的确切尺寸?
喜欢
//char *ptr= malloc( 200 );
char *ptr= malloc( 256 );//instead of 200 we use 256
Run Code Online (Sandbox Code Playgroud)
如果给出2的幂的大小更好,那是什么原因?为什么更好?
谢谢
编辑
我混淆的原因是在Joel的博客Back to Basics中引用
智能程序员通过始终分配大小为2的内存块来最小化malloc的潜在破坏.你知道,4个字节,8个字节,16个字节,18446744073709551616个字节等.由于任何使用乐高的人都应该直观的原因,这可以最大限度地减少自由链中发生的奇怪碎片的数量.虽然看起来这似乎浪费了空间,但也很容易看出它永远不会浪费50%以上的空间.所以你的程序使用的内存不会超过它需要的两倍,这不是什么大不了的事.
对不起,我应该早点发布上面的报价.我很抱歉!
到目前为止,大多数回复都说,以2的力量分配内存是一个坏主意,那么在哪种情况下更好地遵循Joel的观点malloc()呢?他为什么这么说?以上引用的建议现在已经过时了吗?
请解释一下.
谢谢
Tyl*_*nry 54
只需给出您需要的确切尺寸.两个幂的大小可能"更好"的唯一原因是允许更快的分配和/或避免内存碎片.
但是,任何malloc关注高效的非平凡实现都会以这种方式在内部围绕分配,如果适当的话.你不需要关心"帮助"malloc; malloc可以自己做得很好.
编辑:
为了回应你对Joel on Software文章的引用,Joel在该部分中的观点(如果没有你引用的段落之后的上下文很难正确辨别),如果你希望经常重新分配一个缓冲区,它就是更好地这样做是乘法的,而不是相加的.事实上,这正是C++(以及其他)中的std::string和std::vector类所做的.
这是一个改进的原因不是因为你malloc通过提供方便的数字来帮助,而是因为内存分配是一项昂贵的操作,并且你正在努力减少你执行它的次数.乔尔提出了一个时空权衡概念的具体例子.他认为,在需要大量内存动态变化的许多情况下,最好浪费一些空间(通过在每次扩展时分配最多两倍的空间),以节省重复粘贴所需的时间.n每次需要n更多字节时,确切地说就是内存字节数.
乘数不必是两个:您可以根据需要分配最多三倍的空间,最终得到三次幂的分配,或者分配多达五十七倍的空间,最终分配权力为五十七.您执行的分配越多,重新分配所需的频率就越低,但浪费的内存就越多.分配两个权力,最多使用两倍的内存,恰好是一个很好的起点权衡,除非你更好地了解你的需求是什么.
他确实顺便提一下,这有助于减少"自由链中的碎片化",但其原因更多是因为分配的数量和一致性,而不是它们的确切大小.首先,分配和释放内存的次数越多,分割堆的可能性就越大,无论分配的大小是多少.其次,如果你有多个缓冲区,你使用相同的乘法调整大小算法动态调整大小,那么很可能如果一个调整大小从32调整到64,另一个调整大小从16调整到32,那么第二个重新分配可能适合第一个以前是.如果一个人从25改为60,另一个从16改为26,则情况并非如此.
而且,如果你只打算进行一次分配步骤,那么他所说的都不适用.
Gyö*_*sek 18
只是扮演魔鬼的拥护者,这就是Qt如何做到的:
假设我们在QString字符串中附加了15000个字符.然后,当QString空间不足时,发生以下18次重新分配(可能的15000次):4,8,12,16,20,52,116,244,500,1012,2036,4084,6132,8180,10228, 12276,14324,16372.最后,QString分配了16372个Unicode字符,其中15000个被占用.
上面的值可能看起来有点奇怪,但这里有指导原则:
QString一次分配4个字符,直到达到大小20.从20到4084,每次加倍大小.更确切地说,它进入下一个2的幂,减去12.(当请求2的精确幂时,一些内存分配器执行最差,因为它们每个块使用几个字节用于簿记.)从4084开始,它按块进行2048个字符(4096个字节).这是有道理的,因为现代操作系统在重新分配缓冲区时不会复制整个数据 ; 物理内存页面只是重新排序,实际上只需要复制第一页和最后一页上的数据.
我喜欢他们预期代码中的操作系统功能的方式,这些功能意味着从智能手机到服务器群都能很好地运行.鉴于他们比我更聪明,我认为所有现代操作系统都可以使用所述功能.