单个对象内存管理
前文我们已经说了内存管理的原则:只要出现了new alloc retain ,就一定会配对出现一个release,autorelease
那么当我一个对象被释放之后,如果我们再次调用这个对象的方法(包括这个对象的retain release方法),将会出现 野指针 错误,在xcode中具体表现为
EXC_BAD_ACCESS:访问了不可访问的内存空间,就会导致这个错误。
下面这个例子#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString* s = [[NSString alloc]initWithString:@”This is a test string”];
s = [s substringFromIndex:[s rangeOfString:@"a"].location];//内存泄露
[s release];//错误释放
[pool drain];//EXC_BAD_ACCESS
return 0;
}
这个例子当然狠容易的看出问题所在,如果这段代码包含在一个很大的逻辑中,确实容易被忽略。
Objective-C 这段代码有三个致命问题:1、内存泄露;2、错误释放;3、造成 EXC_BAD_ACCESS 错误。
默认情况下,Xcode为了提升编码效率,不会实时监测僵尸对象
开启xcode实时监测僵尸对象的功能
1: 为工程运行时加入 NSZombieEnabled 环境变量,并设为启用,则在 EXC_BAD_ACCESS 发生时,XCode 的 Console 会打印出问题描述。
首先双击 XCode 工程中,Executables 下的 可执行模组,
在弹出窗口中,Variables to be set in the environment,添加 NSZombieEnabled,并设定为 YES,点击选中复选框启用此变量。
这样,运行上述 Objective-C 时会看到控制台输出:Untitled[3646:a0f] *** -[CFString release]: message sent to deallocated instance 0x10010d340
这条消息对于定位问题有很好的提示作用。但是很多时候,只有这条提示是不够的,我们需要更多的提示来帮助定位问题,这时候再加入MallocStackLogging 来启用malloc记录。