instrument -内存泄漏

首先上图,感受下是什么样子的,采用了MRC
instrument -内存泄漏_第1张图片
image.png
  • instrument如下图


    instrument -内存泄漏_第2张图片
    image.png
  • 初始化控制器
    SubViewController * vc = [[SubViewController alloc] init];
    vc.view.backgroundColor = [UIColor redColor];
    [self presentViewController:vc animated:YES completion:nil];
    [vc release];

  • 控制器实现文件
@interface SubViewController ()
@property (nonatomic, strong)NSMutableArray * arrayMTest;
@end

@implementation SubViewController

- (void)dealloc{
    [super dealloc];
    NSLog(@"%s",__func__);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //release test
    NSMutableArray * tempArray = [NSMutableArray new];
    self.arrayMTest = tempArray;
//  self.arrayMTest =  [NSMutableArray new];这种写法需要  [_arrayMTest release];
    for (NSInteger i = 0; i<10000;i++ ) {
        PeopleModel * people1 = [[PeopleModel alloc] init];
        people1.name = @"zhang";
        people1.age = 1;
        [_arrayMTest addObject:people1];
        [people1 release];
    }
    [tempArray release];
}

*********** PeopleModel实现**********
@interface PeopleModel : NSObject
/** name */
@property (nonatomic, copy) NSString *name;
/** age */
@property (nonatomic, assign) NSInteger age;

@end

@implementation PeopleModel

- (instancetype)retain{
    return [super retain];
}

- (oneway void)release{
    [super release];
    
}

- (void)dealloc{
    [super dealloc];
    NSLog(@"%s\n",__func__);
}


*修正后文件

- (void)dealloc{
    [super dealloc];
    [_arrayMTest release];//释放数组
    _arrayMTest = nil;
    NSLog(@"%s",__func__);
}


instrument -内存泄漏_第3张图片
image.png

解释:多次重复创建SubViewController ,然后diss释放,发现内存只增不减,原因数组中的对象没有手动释放,内存泄漏,对数组调用realse 会对其中的对象都调用release方法,同样的removeAllObjects 方法会对数组中的所有对象调用release 操作.

敲黑板:
  • addObject 会调用对象的 retain方法
  • removeAllObjects 会调用对象的release 方法
  • 数组的release 会对其中的所有对象调用release 方法
总结: addObject 操作永远和remove 操作应该最好对等出现,否则就可能内存泄漏,及时释放数组
  • 改造了下,方便对内存管理理解,代码如下:已测试没问题
@interface SubViewController ()
@property (nonatomic, strong)NSMutableArray * arrayMTest;
@property (nonatomic, strong)NSMutableArray * array0Test2;
@property (nonatomic, strong)NSMutableArray * array0Test3;
@property (nonatomic, copy)NSArray * array0Test4;
@end

@implementation SubViewController

- (void)dealloc{
    [_arrayMTest release];
    _arrayMTest = nil;
    [_array0Test2 release];
    _array0Test2 = nil;
    [_array0Test3 release];
    _array0Test3 = nil;
/*_array0Test4 不管是否手动释放,都不会内存泄漏,请思考为什么,下面会给出解释;建议还是手动释放,从内存管理语法层面还是写上去比较好;才采用静态分析的时候会给出错误的提示*/
   // [_array0Test4 release];
   // _array0Test4 = nil;
    
    NSLog(@"%s",__func__);
    [super dealloc];
   
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //release test
    NSMutableArray * tempArray = [NSMutableArray new];
   
    self.array0Test2 = tempArray;
    self.array0Test3 = tempArray;
    self.array0Test4 = tempArray;
    NSLog(@"%ld",_array0Test2.retainCount);
    self.arrayMTest = tempArray;
    NSLog(@"%ld",_arrayMTest.retainCount);
    for (NSInteger i = 0; i<10000;i++ ) {
        PeopleModel * people1 = [[PeopleModel alloc] init];
        people1.name = @"zhang";
        people1.age = 1;
        [_arrayMTest addObject:people1];
        [people1 release];
    }
    [tempArray release];
}



下面分析为啥上面的不需要手动释放instrument也不会出现内存泄漏的问题

请仔细看代码self.array0Test4 = tempArray; 这里其实是copy 生成了一个指定空数组的指针,把带改造一下,在self.array0Test4 = tempArray;之前加一句NSArray * test = [NSArray new];会发现test 和array0Test4 指定的内存地址相容,引申一下所有的 [NSArray new]生成的内存都是同一块。这是系统优化的结果。打印array0Test4 的内存引用计数,结果输出为-1

总结:关于空的不可变数组(NSArray,或者NSDictionary),可以不释放,因为最终系统会维护这一块地址的释放,性能检测不会提示有内存泄漏

你可能感兴趣的:(instrument -内存泄漏)