浅谈内存开辟问题和Block内存问题
我们知道,内存分为栈,堆,块。
栈中的内存由系统自己释放,堆是存对象初始化的地方,块是CPU与内存连接的缓冲器,运行速度比内存快,比CPU慢。
例如,我们NSMutableArray *array = [NSMutableArrar new];
NSMutableArray *array就在栈中,NSMutableArray类型的指针。[NSMutableArray new]开辟的内存在堆中,我们可以理解为
NSMutableArray *array --->[NSMutableArrar new];
栈中的指针指向堆中的对象。
我们用static或者const关键字定义常量,一般在内存块中开辟内存空间。在块中开辟内存空间的对象读写速度最快,但是我们要注意,块的内存很小。
block代码是在块中执行的,所以它的运行速度要比delegate等效率高。但是使用block容易造成内存泄露。
原因在网上找到了:http://www.cnblogs.com/hanjun/p/3767394.html
- NSGlobalBlock:类似函数,位于text段;我们可以通过是否引用外部变量识别,未引用外部变量即为NSGlobalBlock,可以当做函数使用。
- NSStackBlock:位于栈内存,函数返回后Block将无效;
- NSMallocBlock:位于堆内存,NSMallocBlock只需要对NSStackBlock进行copy操作就可以获取。
- Block_copy与copy等效,Block_release与release等效;
- 对Block不管是retain、copy、release都不会改变引用计数retainCount,retainCount始终是1;
- NSGlobalBlock:retain、copy、release操作都无效;
- NSStackBlock:retain、release操作无效,必须注意的是,NSStackBlock在函数返回后,Block内存将被回收。即使retain也没用。容易犯的错误是[[mutableAarry addObject:stackBlock],(补:在arc中不用担心此问题,因为arc中会默认将实例化的block拷贝到堆上)在函数出栈后,从mutableAarry中取到的stackBlock已经被回收,变成了野指针。正确的做法是先将stackBlock copy到堆上,然后加入数组:[mutableAarry addObject:[[stackBlock copy] autorelease]]。支持copy,copy之后生成新的NSMallocBlock类型对象。
- NSMallocBlock支持retain、release,虽然retainCount始终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain;
- 尽量不要对Block使用retain操作。