在關閉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等
三:以上為個人試驗結論,如有不正確地方,歡迎指正!