unity 内存泄漏

内存泄漏,可以通俗解释为“借银行钱不还”(看来和霸气侧漏还不太一样嘛)。在计算机的二进制世界里,操作系统就是银行;每一笔贷款,都是一次内存的申请;而你,就是一个应用程序。即你向银行贷款 = 应用程序向操作系统申请内存。当然,在计算机世界中,我们需要感谢操作系统,因为他是一个不收利息的银行,你借了多少内存,你就只需要还回多少内存。那么我们可以总结一下,内存泄漏的简单定义,就是申请了内存,却没有在该释放的时候释放

如果你总是贷款而不还钱,那么银行里的钱就越来越少,最终导致其他人要借钱时,就无钱可借了。现实生活中,银行为了避免无钱可接,就会把总是借钱不还的人拉入黑名单,不再借他钱;而操作系统则更加凶残,他会直接“做了你”,操作系统将会直接kill掉应用程序。由此可以看出,内存泄漏的危害性与严重性,如果持续泄漏,将因内存占用过大而导致应用崩溃。当然泄漏还有其他的危害,例如内存被无用对象占用,导致接下来的内存分配需要更高的时间成本,从而造成游戏的卡顿等等

 

Unity中的内存泄漏

         在对内存泄漏有一个基本印象之后,我们再来看一下在特定环境——Unity下的内存泄漏。大家都知道,游戏程序由代码和资源两部分组成,Unity下的内存泄漏也主要分为代码侧的泄漏和资源侧的泄漏,当然,资源侧的泄漏也是因为在代码中对资源的不合理引用引起的。

l  代码中的泄漏 –Mono内存泄漏

熟悉Unity的猿类们应该都知道,Unity是使用基于Mono的C#(当然还有其他脚本语言,不过使用的人似乎很少,在此不做讨论)作为脚本语言,它是基于Garbage Collection(以下简称GC)机制的内存托管语言。那么既然是内存托管了,为什么还会存在内存泄漏呢?因为GC本身并不是万能的,GC能做的是通过一定的算法找到“垃圾”,并且自动将“垃圾”占用的内存回收。那么什么是垃圾呢?

我们来联想一下生活中,我们一般把没有利用价值的东西,称为垃圾,也就是没有用的东西,就是垃圾。在GC的世界中,也是一样的,没有引用的东西,就是“垃圾”。因为没有引用了,就意味着对于其他任何对象而言,都认为目标对象对我已经没有利用价值了,那它就是“垃圾”了。根据GC的机制,其占用的内存就会被回收。

基于以上的知识,我们很容易就可以想到为什么在托管内存的环境下,还是会出现内存泄漏了。这就像现实生活中的宅男宅女,吃了泡面总是忘记把盒子扔到门外的垃圾箱里;从计算机的角度来说,则是,在某对象超出其作用域时,我们 “忘记”清除对该无用对象的引用了。

说到这,有的同学可能会有疑问:我每次在代码中申请的内存都非常小,少则几B,多则几十K,现在设备的内存都比较大(几百M还是有的吧),即使泄漏会产生什么大影响么?

首先,水滴石穿的典故相信大家都知道,实际代码中,并非只有显示调用new才会分配内存,很多隐式的分配是不容易被发现的,例如产生一个List来存储数据,缓存了服务器下发的一份配置,产生一个字符串等等,这些操作都会产生内存的分配。你分配几十K,他分配几十K,一会儿内存就没了。

其次,有一点需要说明的是,在Unity环境下,Mono堆内存的占用,是只会增加不会减少的。具体来说,可以将Mono堆,理解为一个内存池,每次Mono内存的申请,都会在池内进行分配;释放的时候,也是归还给池,而不会归还给操作系统。如果某次分配,发现池内内存不够了,则会对池进行扩建——向操作系统申请更多的内存扩大池以满足该次的内存分配。需要注意的是,每次对池的扩建,都是一次较大的内存分配,每次扩建,都会将池扩大6-10M左右(此处无官方数据,是观察所得)。

资源中的泄漏 –Native内存泄漏

资源泄漏,顾名思义,是指将资源加载之后占有了内存,但是在资源不用之后,没有将资源卸载导致内存的无谓占用。

同样的,在讨论资源内存泄漏的原因之前,我们先来看一下Unity的资源管理与回收方式。为什么要将资源内存和代码内存分开讨论,也是因为其内存管理方式存在不同的原因。

上文中说的代码分配的内存,是通过Mono虚拟机,分配在Mono堆内存上的,其内存占用量一般较小,主要目的是程序猿在处理程序逻辑时使用;而Unity的资源,是通过Unity的C++层,分配在Native堆内存上的那部分内存。举个简单的例子,通过UnityEngine命名空间中的接口分配的内存,将会通过Unity分配在Native堆;通过System命名空间中的接口分配的内存,将会通过Mono Runtime分配在Mono堆。

了解了分配与管理方式的区别,我们再来看看回收的方式。如上文所说,Mono内存是通过GC来回收的,而Unity也提供了一种类似的方式来回收内存。不同的是,Unity的内存回收是需要主动触发的。就好比说,我们把垃圾扔在门口的垃圾桶里,GC是每天来看一次,有垃圾就收走;而Unity则需要你打个电话给它,通知它有垃圾要回收,它才会来。主动调用的接口是。其实GC也提供了同样的接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值