iOS中引用計數記憶體管理機制分析總結(NSString引用計數為-1的情況)

來源:互聯網
上載者:User

標籤:style   color   io   os   使用   ar   strong   sp   2014   

在 iOS 中引用計數是記憶體的管理方式,雖然在 iOS5 版本中,已經支援了自動引用計數管理員模式,但理解它的運行方式有助於我們瞭解程式的運行原理,有助於 debug 程式。
   作業系統的記憶體管理分成堆和棧。

   在堆中分配的記憶體,都適用引用計數模式;在棧中則不是。

   NSString 定義的對象是儲存在棧中,所以它沒有引用計數,不是通過引用計數對記憶體進行管理的。之前我在一篇部落格上看,說常量的引用計數會是一個很大的整數,測試的結果顯示它是-1. 對該對象進行 retain 操作,不好改變它的 retainCount 值。

   MutableNSString 定義的對象,需要先分配中的記憶體空間,再初始化才能使用。它是採用引用計數管理記憶體的。對該對象做 retainCount 操作則每次增加一個。

   其實,引用計數是對記憶體地區的空間管理方式,是應從記憶體塊的視角去看的。任何對象都是指向記憶體塊的指標,有多少個指標指向這個記憶體塊,這個記憶體塊就有多少個引用計算。
   如果沒有任何指標指向該記憶體塊了,很明顯,該記憶體塊就沒有對象引用了,引用計算就是 0, 系統會認為該記憶體地區已經空閑,於是立即清理,也就是更新一下管理堆的鏈表中某個標示位。

     測試方法如下:

     在 xcode 中建立一個非 arc 的項目,單視圖即可。建立一個按鈕的操作方法。

     - (IBAction)testRC:(id)sender {

     NSInteger i;
     i=self.i_test;

     if((i%2)==1)
     {
     NSString * [email protected]"welcome";
     NSString * [email protected]"mlgb";
     NSString * str3;
     NSString * [email protected]"welcome";
     NSLog(@"str1 addr is %p",str1); // 你會發現str1與str2兩個指標指向了同一個記憶體
     NSLog(@"str2 addr is %p",str3);
     NSLog(@"str3 addr is %p",str3);
     NSLog(@"str4 addr is %p",str4);

     NSLog(@"str1 retainCount is %i",[str1 retainCount]); // str1與str2是開闢在堆中,因此不能用引用計數來管理記憶體,這裡為-1
     NSLog(@"str2 retainCount is %i",[str2 retainCount]);
     //NSLog(@"str3 retainCount is %i",[str3 retainCount]); 該使用會導致 crash ,因為 str3 沒有指向任何記憶體地區。


     str3=[str1 retain];
     NSLog(@"str3=[str1 retain];");
     NSLog(@"str1 retainCount is %i",[str1 retainCount]);
     NSLog(@"str3 retainCount is %i",[str3 retainCount]);
     str3=[str2 retain];
     NSLog(@"str3=[str2 retain];");
     NSLog(@"str2 retainCount is %i",[str1 retainCount]);
     NSLog(@"str3 retainCount is %i",[str2 retainCount]);

     /*
     結果如下:
     2014-10-09 17:12:57.887 mutableCopy)[4402:60b] str1 addr is 0x3598
  2014-10-09 17:12:57.888 mutableCopy)[4402:60b] str2 addr is 0x35a8
  2014-10-09 17:12:57.889 mutableCopy)[4402:60b] str3 addr is 0x1
  2014-10-09 17:12:57.889 mutableCopy)[4402:60b] str4 addr is 0x3598

     在棧中,內容相同的對象 str1 和 str4 ,都分配在一個記憶體地區中,這點是 c 編譯器的功能,有利於記憶體使用量的效率。

  2014-10-09 17:20:57.132 mutableCopy)[4504:60b] str1 retainCount is -1
  2014-10-09 17:20:57.132 mutableCopy)[4504:60b] str2 retainCount is -1
  2014-10-09 17:20:57.132 mutableCopy)[4504:60b] str3=[str1 retain];
  2014-10-09 17:20:57.133 mutableCopy)[4504:60b] str1 retainCount is -1
  2014-10-09 17:20:57.134 mutableCopy)[4504:60b] str3 retainCount is -1
  2014-10-09 17:20:57.134 mutableCopy)[4504:60b] str3=[str2 retain];
  2014-10-09 17:20:57.135 mutableCopy)[4504:60b] str2 retainCount is -1
  2014-10-09 17:20:57.135 mutableCopy)[4504:60b] str3 retainCount is -1

     */
}
else
{


    NSMutableString * mstr1=[[NSMutableString alloc] initWithString: @"welcome" ];
    NSMutableString * mstr2=[[ NSMutableString alloc ] initWithString : @"mlgb" ];
    NSMutableString * mstr3;
    NSMutableString * mstr4=[[ NSMutableString alloc ] initWithString : @"welcome" ];

    NSLog( @"mstr1 addr is %p" ,mstr1);
    NSLog( @"mstr2 addr is %p" ,mstr2);
    NSLog( @"mstr3 addr is %p" ,mstr3);
    NSLog( @"mstr4 addr is %p" ,mstr4);

    NSLog( @"mstr1 retainCount is %i" ,[mstr1 retainCount]);
    NSLog( @"mstr2 retainCount is %i" ,[mstr2 retainCount]);
    //NSLog(@"mstr3 retainCount is %i",[mstr3 retainCount]);該使用會導致 crash ,因為 str3 沒有指向任何記憶體地區。

    mstr3=[mstr1 retain];
    NSLog( @"mstr3=[mstr1 retain];" );

    NSLog( @"mstr1 retainCount is %i" ,[mstr1 retainCount]);
    NSLog( @"mstr3 retainCount is %i" ,[mstr3 retainCount]);
    NSLog( @"mstr3 addr is %p" ,mstr3);

    mstr3=[mstr2 retain];
    NSLog( @"mstr3=[mstr2 retain];" );
    NSLog( @"mstr2 retainCount is %i" ,[mstr1 retainCount]);
    NSLog( @"mstr3 retainCount is %i" ,[mstr2 retainCount]);
    NSLog( @"mstr3 addr is %p" ,mstr3);

    /*

     2012-07-14 11:07:36.652 testMem[878:f803] mstr1 addr is 0x68706b0
     2012-07-14 11:07:36.655 testMem[878:f803] mstr2 addr is 0x6876040
     2012-07-14 11:07:36.656 testMem[878:f803] mstr3 addr is 0x2a35
     2012-07-14 11:07:36.657 testMem[878:f803] mstr4 addr is 0x686fbf0

  在堆中,內容相同的對象 str1 和 str4 ,都分配在不同記憶體地區中。

  2014-10-09 17:32:49.783 mutableCopy)[4621:60b] mstr1 retainCount is 1
  2014-10-09 17:32:49.783 mutableCopy)[4621:60b] mstr2 retainCount is 1
  2014-10-09 17:32:49.784 mutableCopy)[4621:60b] mstr3=[mstr1 retain];
  2014-10-09 17:32:49.784 mutableCopy)[4621:60b] mstr1 retainCount is 2
  2014-10-09 17:32:49.785 mutableCopy)[4621:60b] mstr3 retainCount is 2
  2014-10-09 17:32:49.785 mutableCopy)[4621:60b] mstr3 addr is 0x8e0e000
  2014-10-09 17:32:49.785 mutableCopy)[4621:60b] mstr3=[mstr2 retain];
  2014-10-09 17:32:49.785 mutableCopy)[4621:60b] mstr2 retainCount is 2
  2014-10-09 17:32:49.785 mutableCopy)[4621:60b] mstr3 retainCount is 2
  2014-10-09 17:32:49.786 mutableCopy)[4621:60b] mstr3 addr is 0x8e0daa0


     */


}

self .i_test= self .i_test+ 1 ;

}


簡而言之,引用計數實際上是指向其記憶體地區的指標數,從記憶體塊的角度去理解,就很容易理解了。

iOS中引用計數記憶體管理機制分析總結(NSString引用計數為-1的情況)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.