概述
这是最近做项目时发现的一个内存管理机制上的一个缺陷,但是我并不知道这究竟是不是一个bug,因为他可以造成内存泄漏,但是却能避开野指针。
详细
一、准备工作
解压memerytest.zip压缩包,用Unity 5.3.3f1 (64-bit)及以上版本打开项目,打开Main场景,就可以测试了。
二、程序实现
第一步,我先创建一个类TestObj,类TestObj在生成时会申请一大块内存创建一个纹理,并且类TestObj中有一个公开方法dddd(原谅我的随便)如下:
using UnityEngine;
using System.Collections;
public class TestObj : MonoBehaviour {
public Texture2D tx2d = null;
public int xxx = 112;
public dui aa;
// Use this for initialization
void Awake () {
tx2d = new Texture2D(2048, 1536, TextureFormat.ARGB32, false, true);
aa = new dui();
}
// Update is called once per frame
void Update () {
}
public void dddd()
{
}
}
第二步,我们需要一个生成TestObj的测试类,这个测试类如下:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class MemeryTesr : MonoBehaviour {
List<GameObject> m_objList = new List<GameObject>();
static List<UnityEngine.Events.UnityAction> m_texList = new List<UnityEngine.Events.UnityAction>();
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void CreateObj()
{
GameObject obj = new GameObject("new obj");
TestObj t2d = obj.AddComponent<TestObj>();
m_objList.Add(obj);
m_texList.Add(t2d.dddd);
}
public void DestroyObj()
{
if (m_objList.Count > 0)
{
Destroy(m_objList[m_objList.Count - 1]);
m_objList.RemoveAt(m_objList.Count - 1);
}
Resources.UnloadUnusedAssets();
}
public void jumpScene()
{
SceneManager.LoadScene("load");
}
}
三、运行效果
我们先生成一大堆对象,点击游戏中的创建对象按钮生成一大堆对象,如下图:

然后点击删除对象,并且跳转场景重新进入此场景,如下图

我们会发现,虽然我们已经Destroy了全部的TestObj附着的GameObject,但是内存中却还会一直驻留着大量没有清理的内存。
其实原因在于我每次新创建的TestObj都把其中的方法dddd放进了static List<UnityEngine.Events.UnityAction> m_texList = new List<UnityEngine.Events.UnityAction>();
而这个是一个静态成员,会一直存在于游戏的整个过程,只要它没有被销毁,则TestObj都会存在于内存中,这虽然能解决新手程序员常写出来的野指针问题,但是却实在是造成内存泄漏。
四、其他补充
打开项目后,项目截图如下:
