我想制作自己的 malloc/free,这样我就可以制作一个精确的复制分配器。
有哪位大师有什么提示和建议吗?
我现在有几个问题:
最佳答案
有很多关于实现 malloc 和类似事物的优秀文献。但我注意到您在此处包含了 C++——您是否知道可以使用 C++ 编写您自己的 new 和 delete 实现?这可能有助于轻松完成此操作。
无论如何,您想要的特性在很大程度上取决于您的工作量,即随时间推移的使用模式。如果您只有 mallocs 和 new frees,那显然很容易。如果您只有一种或几种不同 block 大小的 malloc,那也很简单。
在其他语言中,您可以通过将内存链接在一起来获得一些优势,但 C 就没那么聪明了。
malloc 的基本实现只是简单地分配一个包含数据长度的 header 、一个“使用中标志”和分配的内存。 Malloc 然后在其空间的末尾构造一个新的 header ,分配内存,并返回一个指针。当您释放时,它只会重置正在使用的标志。
诀窍在于,当您执行大量 mallooc 和 free 时,您可以快速获得大量未使用但难以分配的小 blob。所以你需要某种 bumpo gc 来合并内存块。
您可以进行更复杂的 gc,但请记住这需要时间;您不希望空闲时间占用大量时间。
有一个 nice paper在 Solaris malloc 实现上,您可能会感兴趣。这是另一个 on building an alternative malloc ,同样在 Solaris 中,但基本原理是相同的。你应该阅读 Wikipedia article关于垃圾收集,并跟随它到一些更正式的论文。
你知道,你真的应该看看分代垃圾收集器。基本思想是,某些东西保持分配的时间越长,它就越有可能保持分配。这是您提到的“复制”GC 的扩展。基本上,你在内存池的一部分分配新的东西,称之为 g0。当你达到高水位线时,你查看分配的 block 并将仍在使用的 block 复制到内存的另一部分,称之为 g1,然后你可以清除 g0 空间并开始在那里分配。最终 g1 达到它的高水位线,你通过清除 g0 来修复它,并清理 g1 将东西移动到 g0,当你完成后,你将旧的 g1 重命名为 g0,反之亦然,然后继续。
诀窍在于,尤其是在 C 语言中,您分配给 malloc 内存的句柄是直接的原始指针;没有一些大药,你真的无法移动东西。
在评论中,@unknown 问道“移动东西不就是一个 memcpy()”吗?确实如此。但考虑一下这个时间表:
警告:此内容不完整,未经测试,仅供说明,仅供娱乐,不提供明示或暗示的保证
/* basic environment for illustration*/
void * myMemoryHdl ;
unsigned char lotsOfMemory[LOTS]; /* this will be your memory pool*/
分配一些内存
/* if we get past this, it succeded */
if((myMemoryHdl = newMalloc(SIZE)) == NULL)
exit(-1);
在您的 malloc 实现中,您创建内存并返回指向缓冲区的指针。
unsigned char * nextUnusued = &lotsOfMemory[0];
int partitionSize = (int)(LOTS/2);
int hwm = (int) (partition/2);
/* So g0 will be the bottom half and g1 the top half to start */
unsigned char * g0 = &lotsOfMemory[0];
unsigned char * g1 = &lotsOfMemory[partitionSize];
void * newMalloc(size_t size){
void * rtn ;
if( /* memory COMPLETELY exhausted */)
return NULL;
/* otherwise */
/* add header at nextUnused */
newHeader(nextUnused); /* includes some pointers for chaining
* and a field with values USED or FREE,
* set to USED */
nextUnused += HEADERLEN ; /* this could be niftier */
rtn = nextUnused ;
nextUnused += size ;
}
一些东西被释放
newFree(void * aHandle){
*(aHandle-offset) = FREE ; /* set the flag in the header,
* using an offset. */
}
因此,现在您完成了所有工作并达到了最高水位线。
for( /* each block in your memory pool */ )
if( /* block header is still marked USED */ ) {
memcpy(/* block into other partition */);
}
/* clear the partition */
bzero(g0, partitionSize);
现在,返回到您保存在 myMemHdl 中的原始句柄。它指的是什么? (回答,您只需使用 bzero(3) 将其设置为 0x00。)
这就是魔术的用武之地。至少在 C 中,您从 malloc 返回的指针不再受您的控制——事后您无法移动它。在 C++ 中,使用用户定义的类指针类型,您可以解决这个问题。
关于c++ - 我想制作自己的 Malloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/732617/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
是否有self验证的问题列表。看着那个,我可以确定我知道。我应该复习一下。在学习的过程中,我列了一个这样的list,但它只包含我在某处听说过的项目。我需要一段时间才能找到新的东西。 最佳答案 以下是针对ruby和Rails的一些测试列表。证书名称:RubyonRails谁提供:oDeskIncorporation认证费用:免费网站:https://www.odesk.com/tests/985?pos=0证书名称:RubyonRails提供者:Techgig.com(TimesBusinessSolutionsLimited(T
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=
出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t
我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc