学习了OC中的内存管理,记录一下内存管理中常见的三个问题:野指针,内存泄露,内存过度释放。
首先,创建一个Person 类,完成属性设置,name ,sex,age
再设置一个便利构造器类方法,来设置属性值
前提介绍完了,下面看一下常见错误代码:
第一个要介绍的是野指针错误,即指向一个你没有所有权的内存空间,并且该内容空间已经被释放
@autoreleasepool {
Person *person = [PersonpersonWithName:@"jack"sex:@"man"age:22];
[personsaySelf];
[personretain];//2
NSLog(@"%ld",[personretainCount]);
[personrelease];//1
NSLog(@"%ld",[personretainCount]);
[personrelease];//0
NSLog(@"%ld",[personretainCount]);
//野指针 *person
[personsaySelf];
}
前面已经释放了空间,但是指针没有指空,指向的空间是我们不可控制的,所以就会崩溃。
解决办法就是,使指针指空。
@autoreleasepool {
Person *person = [PersonpersonWithName:@"jack"sex:@"man"age:22];
[personsaySelf];
[personretain];//2
NSLog(@"%ld",[personretainCount]);
[personrelease];//1
NSLog(@"%ld",[personretainCount]);
[personrelease];//0
NSLog(@"%ld",[personretainCount]);
//野指针 *person
person =nil;
[personsaySelf];
}
第二个问题就是内存过度释放问题:
@autoreleasepool {
Person *person = [PersonpersonWithName:@"jack"sex:@"man"age:22];
[personsaySelf];
[personretain];//2
[personretain];//3
[personrelease];//2
[personrelease];//1
[personrelease];//0
[personrelease];//过度释放
[personsaySelf];
}
这个问题比较简单,就是对释放过的内存再次释放,导致崩溃。
第三个问题就是内存泄露,一道面试题,就是内存泄露问题,我们先来看问题代码:
@autoreleasepool
{
for (NSInteger i =0; i <100000000000000000; i++)
{
Person *person = [PersonpersonWithName:@"zhaozhao" sex:@"girl"age:24];
[personautorelease];
}
}
这道题是道典型的内存泄露问题,每一次申请空间都没有释放,仅仅是放入了自动释放池,这时候每个对象的引用计数器都是1,不是0,不会释放内存,而这个循环的条件很大,内存被申请完了,自动释放池还没有释放,导致了最后内存的泄露。
解决方案:
@autoreleasepool
{
for (NSInteger i =0; i <100000000000000000; i++)
{
@autoreleasepool {
Person *person = [PersonpersonWithName:@"zhaozhao"sex:@"girl" age:24];
[personautorelease];
} //每一次创建都释放,就不会导致内存泄露
}
}
还有一个问题就是常量区的引用计数无限的,无法被释放。来看一个例子:
@autoreleasepool {
Person *person = [Person personWithName:@"jeff" sex:@"man" age:24];
person = @"aaa";//常量区的引用计数为无穷大,无法释放
[person release];
NSLog(@"计数器 %ld",[personretainCount]);
}
当我们运行程序的时候会看到输出的引用计数器 为 -1。
接下来的一个问题就是指针的重定向问题引发的内存管理错误。
@autoreleasepool {
Person *person = [Person personWithName:@"jeff" sex:@"man" age:24];
person = [[Person alloc] init];
[person release];// 0
NSLog(@"计数器 %ld",[personretainCount]);
[person release];//指针重指向新的堆 过度释放
NSLog(@"计数器 %ld",[personretainCount]);
}