Cocos2d-x 的内存管理
既然选择了C++作为游戏开发的语言, 手动的管理内存是难以避免的, 而Cocos2d-x的仿Objctive-C的内存管理方式, 事实上让问题变得更加复杂(仅仅是移植更加方便了), 因为你需要很好的掌握两种语言的内存管理方式, 并且在使用时头脑清晰, 不能混用, 不然等待你的就是无穷的噩梦, 因为引用计数的原因, 问题比起纯粹的C++内存泄漏还要难以定位的多.
这里统一的整理一下目前在Cocos2d-x中的内存管理相关的方法和问题. 为了让思路更加清晰, 我提及的不仅仅是具体在Cocos2d-x中怎么用, 也包含一些为啥在Cocos2d-x中应该这么用.
并且, 因为以下讲到的每个点要讲的详细了, 其实都可以写一整篇文章了, 没法在短时间内详述, 这篇文章也就仅仅作为一个引子而已.
C++的内存管理
C语言的malloc, free
因为C++基本兼容C, 所以C语言的malloc和free也是支持的. 简单的说用法就是malloc后记得free即可.
#include <stdio.h>
#include <stdlib.h>
const size_t kBufferSize = 16;
void test() {
char *buffer = (char*)malloc(kBufferSize);
memset(buffer, 0, sizeof(char) * kBufferSize);
sprintf(buffer, "%s", "Hello World\n");
printf(buffer);
free(buffer);
}
int main(int, char**) {
test();
return 0;
}
当然, 还有realloc和calloc这两个平时较少用的内存分配函数, 这里不提了, 在C语言时代, 我们就是用malloc和free解决了我们的内存问题. 重复的对同一段内存进行free是不安全的, 同时, 为了防止free后, 还拿着指针使用(即野指针), 我们一般使用将free后的内存置空.
因为这种操作特别的多, 我们常常会弄一个宏, 比如Cocos2d-x中的
#define CC_SAFE_FREE(p) if(p) { free(p); p = 0; }
C++的new, delete, new[], delete[]
为什么malloc和free在C++时代还不够呢? malloc,free在C++中使用有如下的缺点:
malloc和free并不知道class的存在, 所以不会调用对象的构造函数和析构函数.
malloc返回的是void*, 不符合C++向强类型发展的趋势.
于是, BS在C++中增加了new-delete组合以替代malloc, free. 其实new, delete基本上都是用malloc, free实现的更高层函数, 只是增加了构造和析构的调用而已. 所以在平时使用的时候并无区别, 但是因为malloc其实是记录了分配的长度的, 长度以字节为单位, 所以一句malloc对应即可, 不管你是malloc出一个char, 一个int, 还是char的数组或者int的数组, 单位其实都是字节. 而长度一般记录在这个内存块的前几个字节, 在Windows中, 甚至可以使用_msize函数从指针中取出malloc出的内存长度.
而new的时候有两种情况, 可以是一个对象, 也可以是对象的数组, 并且, 没有统一的记录长度. 使得我们需要通过自己记住什么时候new出了一个对象, 什么时候new出了多个对象. 这个问题最近云风还吐槽过. 并且增加了delete[]用于删除new出多个对象的情况. 让问题更加容易隐藏不被发现的是, 当你讲delete用于new[]分配的内存时, 实际相当于删除了第一个对象, 是完全正确的语法, 不会报任何错误, 你只能在运行出现诡异问题的时候再去排查.
这个问题实际是语言设计的决策问题. 在BS这个完美主义者这里, C++语言的设计原则之一就是零负荷规则 — 你不会为你所不使用的部分付出代价. 并且在这里这个规则执行的显然是要比C语言还要严格. 当你只分配一个对象的时候, 为啥要像分配多个对象时一样, 记录一个肯定为1的计数呢? 估计BS是这么想的. 于是我们只好用人工来区分delete和delete[]. 某年某月, 我看到某人说C++是实用主义, 我笑了, 然后我看到C++的一条设计原则是”不一味的追求完美”, 我哭了……
相关新闻>>
- 发表评论
-
- 最新评论 更多>>