NSMutableArray 內存釋放分析


在關閉ARC情況下對NSMutableArray存儲內存分析。

一:測試環境構建

1:創建一個簡單視窗工程 在AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    ViewController *viewCtrl =[[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
    UINavigationController *navigationCtrl = [[UINavigationController alloc] initWithRootViewController:(UIViewController*) viewCtrl];
    self.viewController =  (ViewController*)navigationCtrl;
    self.window.rootViewController = self.viewController;
    [navigationCtrl release];
    [self.window makeKeyAndVisible];
    return YES;
}

 

2 在ViewController.m中

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UIBarButtonItem *rightItm = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(rightTarget:)];
    self.navigationItem.rightBarButtonItem = rightItm;
    
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"根視圖" style:UIBarButtonItemStyleDone target:nil action:nil];
    self.navigationItem.backBarButtonItem = backButton;
    [backButton release];
    
    [rightItm release];
}

-(void)rightTarget:(id)sender
{
    SecondViewController *secondViewCtrl = [[SecondViewController alloc] init];
    [self.navigationController pushViewController:secondViewCtrl animated:YES];
    [secondViewCtrl release];
}

3在 SecondViewController.h中申明如下:

 NSMutableArray *arrayObj;

 SecondViewController.m中實現

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        // Custom initialization
        [self.view setBackgroundColor: [UIColor grayColor] ];
        [self initArrayData];
    }
    return self;
}
-(void)initArrayData
{
    arrayObj = [[NSMutableArray alloc] initWithCapacity:0];
    DataSorceViewController *dataViewCtrl = nil;
    for (int i = 0 ; i < 1024; i++)
    {
        dataViewCtrl = [[DataSorceViewController alloc] init];
        [arrayObj addObject: dataViewCtrl];
    }
    
}
-(void)viewWillDisappear:(BOOL)animated
{
    
    
    for ( DataSorceViewController *data in arrayObj)
    {
        [data release];
        data = nil;
    }
     
    [arrayObj removeAllObjects];
    [arrayObj release];
    arrayObj = nil;
}

4 引入測試用的數據對象 DataSorceViewController,這里用的UIViewController子類,可以用任何類型的數據做為測試

 

二 :測試操作

1,SecondViewController.m 的  -(void)viewWillDisappear:(BOOL)animated 中不做任何操作。用profile memeory leak測試,當頁面切換操作后發現,有紅色標注,表示有內存泄漏。

2. -(void)viewWillDisappear:(BOOL)animated函數中加入 

 [arrayObj release];

 arrayObj = nil;

 

切換頁面,profile memeory leak中沒有發現有紅色標注,表示沒有內存泄漏嗎?其實不然,在Statistics的數據對象列表中,DataSorceViewController 對象始終存在,而且在多次切換操作中DataSorceViewController對象所占的內存每切換一次就會增長一次。多次切換后內存DataSorceViewController對象占用內存居高不下。

3:-(void)viewWillDisappear:(BOOL)animated函數中加入

[arrayObj removeAllObjects];
[arrayObj release];
arrayObj = nil;

效果同第二步。

4:增加對數組對象釋放操作

for ( DataSorceViewController *data in arrayObj)
    {
        [data release];
        data = nil;
    }
     
    [arrayObj removeAllObjects];
    [arrayObj release];
    arrayObj = nil;

在頁面每次切換以后,DataSorceViewController 對象被釋放。

 

結論:

一:profile memeory leak 檢測,那個紅色的標示並不是可靠的,即使有內存泄漏,leaks紅色標示也可能沒有出現

二:NSArray(NSMutableArray)數組,在 addObject 操作是會對對象做retain操作,同時 removeobject 操作會對對象做release操作,但數組中保存的對象所占的內存並沒有釋放,因為alloc操作時候retaincount 為1,一次addObject操作,retaincount 2,rimoveObject操作,retaincont為1,實際內存並沒有得到釋放。要真正釋放內存,要遍歷數組,對數組中保持的每個對象做release操作。 最后清除數組所有對象以及其本身。同理可得其它容器也是相同性質,比如NSDictionary等

三:以上為個人試驗結論,如有不正確地方,歡迎指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM