【问题标题】:iPhone NSMutableArray Memory LeakiPhone NSMutableArray 内存泄漏
【发布时间】:2011-01-21 12:18:51
【问题描述】:

Xcode Instruments 声称以下代码会导致内存泄漏。据我了解,分配属性时会发生以下情况:
* 旧值是自动释放的
* 保留新值
* 新值赋值明显
考虑到这一点,我怎么会有内存泄漏,我该如何解决呢?

“TestProjectViewController.h”:

#import <UIKit/UIKit.h>

@interface TestProjectViewController : UIViewController {
    NSMutableArray* array;
}

@property (nonatomic, retain) NSMutableArray* array;

@end

“TestProjectViewController.m”:

#import "TestProjectViewController.h"

@implementation TestProjectViewController

@synthesize array;

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    for(int i = 0; i < 5; i++) {
        self.array = [[NSMutableArray alloc] init];
        [self.array addObject:@"Hello world #1"];
        [self.array addObject:@"Hello world #2"];
    }
}

【问题讨论】:

    标签: iphone memory-leaks nsmutablearray


    【解决方案1】:
    self.array = [[NSMutableArray alloc] init];
    

    在这里你保留了两次新的数组对象 - 分配它时,然后在 setter 方法中。以下其中一项应该可以解决此问题:

    self.array = [[[NSMutableArray alloc] init] autorelease];
    // or
    self.array = [NSMutableArray arrayWithCapacity:someNumber];
    

    并且不要忘记在 dealloc 方法中释放你的数组。

    【讨论】:

    • 如果是属性为“retain”的属性,需要手动释放数组吗?
    • 绝对是。也可以通过调用self.array = nil;来释放数组
    • 是的,属性“retain”属性定义了相应 setter 方法的行为 - 您增加对象的保留计数,因此必须在此之后释放该对象。如果您更改属性值 - 旧对象将自动释放。如果你销毁你的对象,你必须释放所有(以前保留的)它的成员。如果需要,您可以在 dealloc 方法中调用 self.array = nil 而不是显式释放
    【解决方案2】:

    每次循环,你alloc 一个新数组。每个数组以 1 的引用计数开始,分配给属性会将其增加到 2。您需要 release 这些数组,以便属性是对象的唯一“所有者”。

    例如,您可以这样做:

    - (void)applicationDidFinishLaunching:(UIApplication *)application {    
        for(int i = 0; i < 5; i++) {
            self.array = [[NSMutableArray alloc] init];
            [self.array addObject:@"Hello world #1"];
            [self.array addObject:@"Hello world #2"];
            [self.array release];
        }
    }
    

    或者这样做:

    - (void)applicationDidFinishLaunching:(UIApplication *)application {    
        for(int i = 0; i < 5; i++) {
            self.array = [[[NSMutableArray alloc] init] autorelease];
            [self.array addObject:@"Hello world #1"];
            [self.array addObject:@"Hello world #2"];
        }
    }
    

    【讨论】:

      【解决方案3】:

      您正在循环内初始化数组。这不是必需的,至少您将数组的值分配给另一个对象。在这种情况下,您还必须在循环内释放它。您也没有释放内存。既然你为数组分配了内存,你也应该释放它:

      - (void)applicationDidFinishLaunching:(UIApplication *)application {    
        self.array = [[NSMutableArray alloc] init];//You just need to initialize the array just once
        for(int i = 0; i < 5; i++) {
          [self.array addObject:@"Hello world #1"];
          [self.array addObject:@"Hello world #2"];
        }
      }
      //Finally its necessary to release the memory when the app quits using the release method 
      [self.array release]
      

      【讨论】:

        【解决方案4】:

        此方法泄漏是因为alloc/init 具有隐式保留,然后该属性会再保留一次。这导致每个数组被保留两次。您可以在循环结束时autorelease 数组或release 它。

        顺便说一句,为什么要在循环中分配这样的属性?只有最后一个数组将保留在该属性中。相反,您可以使用局部变量并仅分配最后一个数组:

        - (void)applicationDidFinishLaunching:(UIApplication *)application { 
            NSMutableArray *tempArray = nil;
        
            for(int i = 0; i < 5; i++) {
                tempArray  = [[[NSMutableArray alloc] init] autorelease];
                [tempArray addObject:@"Hello world #1"];
                [tempArray addObject:@"Hello world #2"];
            }
        
            self.array = tempArray;
        }
        

        【讨论】:

          猜你喜欢
          • 2012-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-23
          • 2011-12-10
          • 2011-05-24
          相关资源
          最近更新 更多