要找工作的小学弟问我一个问题,内存溢出,内存泄露是什么,他们之间有什么关系?我想了想回答
内存溢出:内存不够用
内存泄露:无法使用的内存
本来这种度娘能出一堆答案的问题就不好回答,这么回答肯定没人满意,比如我没有回答他们之间的关系,比如正在使用的内存怎么可以成为内存泄露呢?没办法,改下答案吧
内存溢出:内存实在不够用
内存泄露:无法使用应该可以使用的内存
这样的回答又被吐槽了,什么叫实在,什么叫应该?为什么还不回答他们的关系?为什么没有栗子?尼玛,这么脑补的东西让我回答,一定有坑,但谁让我乐于助人累

内存溢出
描述: 内存不够用
场景:无法获取足够的内存,程序就会报out of memory
解决办法:重启,修改配置(软),加内存条(硬)

内存泄露

描述:无法使用的内存
场景:内存是拿来用的,在使用的时候肯定是私有的,自己需要的服务占用内存就是正确的,而自己不需要的服务都可以成为内存溢出,诸如某些安全卫士,不管你怎么关,怎么删,怎么卸载都能强,奸的桌面情况也算

关系:内存泄露表达的是不合理使用内存的一种现象,内存溢出是一种事实存在是现象,完全没有任何关系,软件最喜欢的就是单一原则,所有的关系自行脑补,当然2者都对内存卸载有需求,内存卸载的方案是他们共同需求

比如javascript内存回收方案(大多数情况都是这样)

通过引用计数算法进行内存回收,这个方案很纯粹,简单的讲就是在图,树,森林的关系结构中,图不好回收,remove后可能还是图/树,树容易回收,remove后就变成森林,森林肯定可以回收(回收那些不需要存在的树)

假设切除a与root的关系,a会被孤立起来,即可以被回收

假设切除b与root的关系,b依然不会被孤立起来,整个结构依然是一个图(树),不存在独立的结构


js具体栗子,丢到html里试试

<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
    $(function() {
        var a = $("#test");
        $("#a").click(function() {
            $("#test").remove();
            console.log(a);
            console.log($("#test"));
        })
    })
</script>
<input id="test">
<input type="button" id="a">

点击那个按钮,或者执行$("a").click(),猜猜会显示什么


document被删除,其引用就应该消失是正确的,此时a存在window下,domcument也存在window下,这种相互引用的关系构成了比较复杂的图,回收器不会认为domcument为主体/原始/母体数据(反正他被删了,其他引用全应该消失),依然保留a节点,这是正确的,但不是我们需要的


解决方式:1.闭包中不去引用可能被删除的对象2.不对主体数据(这里的domcument就是),追加属性,或被追加3.构造自己的引用系统(除了系统自带的数据意外就是自己的数据,也可以理解为缓存系统),已达到给主体数据添加自定义数据的目的

自定义引用/缓存系统(标题党)

引用是缓存的形式,所有的引用仅仅代表指针,而不是具体的内容(内容只有一份),比如最简单的例子

当a={a:"a"},b=a时,若a={},求b,所有人都知道答案,这就是一种缓存的方式,任何指向都可以对缓存进行数据的添加和修改,但是没有办法删除

比如在dom节点中

如果我想让dom1被删除时,所有引用dom1的引用全部失效,只能通过分层的方式(换句话说,其他的引用必须通过一个固定的接口去查找并获取dom1,这就是为什么面向对象语言首先要面向get/set)

即使称之为缓存系统,还不如说是一套具体的规范。。。


总之一句话
内存溢出:内存不够用
内存泄露:无法使用的内存
面试坑死人

posted on 2015-02-26 16:36  Glimis  阅读(206)  评论(0编辑  收藏  举报