2011-12-12 66 views
2
- (void)foo 
{ 
    @try { 
     for (id o in os){ 
      @autoreleasepool { 
       for (id o2 in moreOs){ 
         // create a lot of autoreleased objects. 
       } 
       //exception raised 
      } 
     } 

    } 
    @catch (NSException *exception) { 
    // handle the exception 
    } 
} 
  1. 將編譯器重寫上面的代碼排空水池的異常的情況下,還是會泄露?@autorelease指令和異常處理

  2. 如果編譯器確實重寫了它,它會怎麼做?

+2

請注意,以任何理由,但表示無法恢復的程序故障異常的使用是對SDK的設計模式一節「自動釋放池和嵌套自動釋放池的影響範圍」。如果您的異常拋出系統框架代碼的堆棧框架,則行爲未定義。 – bbum

回答

2

爲了解決您的問題,沒有那些在該池中創建的對象將被有效泄漏,直到某些自動釋放池進一步向下排放。除了您的應用程序的主要autoreleasepool可能沒有被釋放一段時間以外,可能沒有遊戲池進一步向下。

如果發現異常,則嘗試執行以下操作以在此方法返回時強制排空。

- (void)foo 
{ 
    @autoreleasepool { 
     @try { 
      for (id o in os){ 
       @autoreleasepool { 
        for (id o2 in moreOs){ 
         // create a lot of autoreleased objects. 
        } 
        //exception raised 
       } 
      } 

     } 
     @catch (NSException *exception) { 
      // handle the exception 
     } 
    } 
} 

根據文檔,當最外面的autoreleasepool排空時,它也會排除任何嵌套的。

如果排出一個自動釋放池不是堆的頂部,所有的(未發行)自動釋放池上面的堆棧被排出(和他們的所有對象發送相應的釋放消息)。如果你在完成之後忽略了向自動釋放池發送消耗(不推薦的東西),當其中一個自動釋放池被耗盡時,該池將被耗盡。

Advanced Memory Management Programming Guide

4

它會不是排水池。從Transitioning to ARC Release Notes

在輸入時,會推送自動釋放池。在正常退出(中斷,返回,轉到,後退等)時,autorelease池會彈出。爲了與現有代碼兼容,如果退出是由於異常造成的,則autorelease池不會彈出。