精通Cocos2d-x游戏开发(基础卷)
上QQ阅读APP看书,第一时间看更新

4.5 野指针和内存泄漏

野指针和内存泄漏是使用指针的时候较容易出现的问题,野指针是指指向垃圾内存的无效指针,而内存泄漏则主要是指在堆上面新建出来的内存没有被释放。

当声明了一个指针,但并不打算为指针赋值时,应该把指针初始化为NULL,否则指针会指向一个随机的地址。

当将一个新建出来的指针删掉之后,则指向的这块内存也无效,因此应该把它设置为NULL。

如果将一个函数的局部变量的地址返回给指针,那么这块地址也是无效的。

对这些指针进行操作是非常危险的,一般程序员在使用指针的时候,会在前面加上是否NULL的判断,加上该判断之后会感觉很有“安全感”,但是野指针可以直接渗透进来,并对程序造成致命性的打击。

相对野指针,内存泄漏就隐蔽多了。不管是在编译中还是在运行中,都很难发现明显的问题,但假设内存泄漏的地方被重复执行,时间久了就会耗尽内存。这种问题一般在服务端程序中会较严重一些,因为服务器需要长时间运行。在PC客户端上这个问题不算严重,但是在手机上,虽然现在硬件发展很快,但是大部分手机的内存还是比较小的,特别是在一些老爷机上,稍微多一点的内存泄漏就可以使系统崩溃,所以,应小心维护好在堆上面分配的内存。

曾经有个朋友写了这样一个函数,在函数的开始新建了一块内存,然后在函数返回之前,删掉它,这个代码本身没有内存泄漏,之后,他在维护这份代码的过程中,向其中加了一些错误判断,如果发生错误,返回什么,相信很多人都写过这样的代码,但他在添加这些代码时,所有的返回语句都忘记把这块内存删掉了,所以内存在缓慢地增长着。

要检测内存泄漏,可以通过一些内存泄漏检测工具来做,这里介绍一个老方法,就是在对象的构造函数和析构函数中来统计,创建了多少对象,释放了多少对象,程序运行结束后查看日志,就可以发现是否有内存泄漏了。

//定义静态变量
static int gGameObjectCount = 0;
 //构造函数打印统计
CGameObject::CGameObject(void)
{
    CCLog("CGameObject count %d", ++gGameObjectCount);
}
 //析构函数打印统计
CGameObject::~CGameObject(void)
{
    CCLog("~CGameObject count %d", --gGameObjectCount);
}