【IOS學習基礎】內存管理

一、內存幾大區域

1> 棧區:局部變量(基本數據類型、指針變量)。
2> 堆區:程序運行的過程當中動態分配的存儲空間(建立的對象)。
3> BSS段:沒有初始化的全局變量和靜態變量。
4> 數據區:已經初始化的全局變量和靜態變量。(字符串常量)
5> 代碼段:程序編譯後的代碼的內容。

 

二、引用計數器

1> 引用計數器:每一個繼承自NSObject的對象都有一個引用計數器,用來表示當前對象有幾個擁有者。
2> 引用計數器的做用:用來判斷對象是否應該回收。
3> 引用計數器的操做(ARC下沒法使用)
 * retain  引用計數器+1
 release  引用計數器-1 
 retainCount 獲得引用計數器的值(點擊進入NSObject.h文件,有一個 - (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE 的方法)
 注:任何一個OC對象,只要一被建立出來,其引用計數默認爲1;一個對象的引用計數歸0的時候,對象就會被銷燬。

 

三、關於dealloc方法

1> 對象被釋放時會自動調用
2> 開發中常常重寫對象的dealloc方法,用於觀察對象何時被釋放或者想要在對象釋放以前作些相應的操做,dealloc方法能夠看作是對象的「臨終遺言」。
3> 在MRC下,重寫dealloc要注意必需要在其最後調用[super dealloc]

 

四、殭屍對象、野指針、空指針。

1> 殭屍對象:即指已經被銷燬的對象(不能再使用的對象)
2> 野指針:指向殭屍對象(不可用內存)的指針,給野指針發送消息會報「EXC_BAD_ACCESS"錯誤(常見錯誤)。
3> 空指針:沒有指向存儲空間的指針(nil),給空指針發送消息沒有任何反應,試想一下,用nil調用方法怎麼可能有反應。而解決野指針錯誤的方法就是將對象的指針變爲空指針。
// 先開啓殭屍對象檢測
 NSObject *obj = [[NSObject alloc] init]; [obj release]; // 野指針錯誤
[obj log:@"測試"];


// 輸出臺打印
2016-01-21 19:35:46.367 內存管理[2688:205046] *** -[NSObject log:]: message sent to deallocated instance 0x100113c80 (向一個已經被釋放的實例對象發送了消息)

 

5、開發中關於ARC(自動內存管理)和MRC(手動內存管理)的經常使用操做

1> 將工程從ARC環境改成MRC環境(如今基本上都是ARC環境,保持默認便可)
搜索框中輸入「auto」
將「YES」改成「NO」,即從ARC改成MRC了,反之改成「YES「就是從MRC改成ARC
 
2> 工程整體環境是ARC的,讓工程中某個類支持MRC
開發中,咱們有時候可能用到一些之前的類,而有些比較老的類庫又是MRC環境的,那麼能夠選擇增長編譯開關"-fno-objc-arc」(這裏以GDataXMLNode類爲例)
除了關於「libxml.dylib」動態庫錯以外,初次將GDataXMLNode導入工程的時候,會出現大約二十個錯誤,按照以下圖操做便可
  
 
3> 檢測野指針(殭屍對象)錯誤
   
 

六、關於nil、Nil、NULL

1> nil是一個對象值(對象爲空)  將對象等於nil。能夠防止調用殭屍對象報錯
2> Nil是一個類對象(類對象爲空)
3> NULL是一個通用指針(泛型指針)
4> [NSNull null]是一個對象,用在不能使用nil的場合。
 

七、@property參數

1> 控制set方法的內存管理
  retain : release舊值,retain新值(用於OC對象)
  assign : 直接賦值,不作任何內存管理(默認,用於非OC對象類型)
  copy   : release舊值,copy新值(通常用於NSString,保證字符串的安全性)
 
2> 控制需不需生成set方法
  readwrite :同時生成set方法和get方法(默認)
  readonly  :只會生成get方法
  
3> 多線程管理
  atomic    :性能低(默認)
  nonatomic :性能高
 
4> 控制set方法和get方法的名稱
  setter : 設置set方法的名稱,必定有個冒號:
  getter : 設置get方法的名稱
 

八、NSString在內存管理中的問題

// 最近在網上視頻上看到的一個有趣的問題,按照視頻上所講 // 字符串有一個常量池 // 若是你須要的字符串在常量池中已經存在了,不會分配內存空間 // 使用字符串的時候:採用下面一、三、5方式獲取的字符串都在常量區(嗯,這三個NSString對象跟視頻上講的同樣,確實在字符常量區,由於打印其引用計數是一個巨大的數,因此判斷其內存不歸用戶管) // 注意:視頻上所講,str2和str4的應該被分配在堆區,即內存歸用戶管,引用計數應該爲1 // 但事實上,看下面打印的str2和str4?瞬間凌亂了,Why,說好的在堆區呢?
 NSString *str1 = @"abc"; NSString *str2 = [NSString stringWithFormat:@"aaa"]; NSString *str3 = [NSString stringWithString:@"abc"]; NSString *str4 = [[NSString alloc] initWithFormat:@"aaa"]; NSString *str5 = [[NSString alloc] initWithString:@"abc"]; NSString *str6 = [[NSString alloc] init];  // 在棧區?爲啥它的引用計數那麼大?
        NSLog(@"str1 = %@ , %p , %lu",str1,str1,str1.retainCount); NSLog(@"str2 = %@ , %p , %lu",str2,str2,str2.retainCount); NSLog(@"str3 = %@ , %p , %lu",str3,str3,str3.retainCount); NSLog(@"str4 = %@ , %p , %lu",str4,str4,str4.retainCount); NSLog(@"str5 = %@ , %p , %lu",str5,str5,str4.retainCount); NSLog(@"str6 = %@ , %p , %lu",str6,str6,str5.retainCount);

// 打印

  2016-01-21 21:26:36.979 NSString內存管理問題[3269:255674] str1 = abc , 0x100004230 , 18446744073709551615安全

  2016-01-21 21:26:36.980 NSString內存管理問題[3269:255674] str2 = aaa , 0x61616135 , 18446744073709551615多線程

  2016-01-21 21:26:36.981 NSString內存管理問題[3269:255674] str3 = abc , 0x100004230 , 18446744073709551615性能

  2016-01-21 21:26:36.981 NSString內存管理問題[3269:255674] str4 = aaa , 0x61616135 , 18446744073709551615測試

  2016-01-21 21:26:36.981 NSString內存管理問題[3269:255674] str5 = abc , 0x100004230 , 18446744073709551615atom

  2016-01-21 21:26:36.981 NSString內存管理問題[3269:255674] str6 =  , 0x7fff7c51bd00 , 18446744073709551615spa

  // 而後說在IOS項目下又不同,我姑且又試了一試,確實是內存地址不同了,可是引用計數是什麼鬼線程

  2016-01-21 21:30:42.632 NSString內存管理[3289:257683] str1 = abc , 0x106f4c050 , 184467440737095516153d

  2016-01-21 21:30:42.633 NSString內存管理[3289:257683] str2 = aaa , 0xa000000006161613 , 18446744073709551615指針

  2016-01-21 21:30:42.633 NSString內存管理[3289:257683] str3 = abc , 0x106f4c050 , 18446744073709551615code

  2016-01-21 21:30:42.633 NSString內存管理[3289:257683] str4 = aaa , 0xa000000006161613 , 18446744073709551615

  2016-01-21 21:30:42.633 NSString內存管理[3289:257683] str5 = abc , 0x106f4c050 , 18446744073709551615

  2016-01-21 21:30:42.633 NSString內存管理[3289:257683] str6 =  , 0x107279380 , 18446744073709551615

  // 最後,我不死心,又試了一下

  NSArray *array1 = [[NSArray alloc] init];

  NSLog(@"array1 = %lu",array1.retainCount);

  NSMutableArray *array2 = [[NSMutableArray alloc] init];

  NSLog(@"array2 = %lu",array2.retainCount);

 // 打印 

  2016-01-21 21:48:01.828 NSString內存管理問題[3447:267148] array1 = 2  // 媽蛋  爲何是2

  2016-01-21 21:48:01.828 NSString內存管理問題[3447:267148] array2 = 1

 // 最後

  看到最後,有這麼一張圖

  

    總結一下吧,不要相信retainCount的值。(不要用它去作判斷)

  日常都在用ARC,也沒注意到有這些問題,既然看到了,就權當了解一下。

  
  
好記性不如爛筆頭!多多複習基礎知識,一一記錄下來仍是有所收穫的! 
相關文章
相關標籤/搜索