2012-05-15 94 views
4

我有一個問題,我似乎無法弄清楚。完成了大量的搜索,並嘗試了大約50個不同的變體,到目前爲止沒有骰子。這是我的困境。NSData內存不能釋放 - ARC

我有3種方法。一個在我的PageView對象加載時調用,另一個在用戶進行更改時調用,最後一個用戶在用戶離開頁面時調用。

第一種方法:

- (void)captureInitialLinesTexture { 
@autoreleasepool { 
    self.initialLinesTextureCaptured = TRUE; 
    GLubyte *buffer =(GLubyte *) malloc (1024 * 1024 * 4 * sizeof(GLubyte)); 
    glPixelStorei(GL_PACK_ALIGNMENT,1) ; 
    glReadPixels(0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 
    glBindTexture(GL_TEXTURE_2D, [pageTexture name]); 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 
    NSData __autoreleasing *tempData = [NSData dataWithBytes:buffer length:1024*1024*4*sizeof(GLubyte)]; 
    if (textureData == nil) { 
     textureData = [self.pageController.notebookDoc newTextureInPage:self.page]; 
    } 

    [pageTextures addObject:tempData]; 
    if ([pageTextures count] > 5) { 
     [pageTextures removeObjectAtIndex:0]; 
    } 
    textureData.textureData = tempData; 
    textureData.page = self.page; 
    self.page.texture = textureData; 
    self.page.lastLineId = [NSNumber numberWithInt:self.pageController.newLineId - 1]; 
    [self.pageController saveNotebookWithUndo:FALSE]; 
    free((GLubyte*)buffer); 
    } 
} 

方法二:

-(void)capturePageTexture { 
@autoreleasepool { 
    GLubyte *buffer =(GLubyte *) malloc (1024 * 1024 * 4 * sizeof(GLubyte)); 
    glPixelStorei(GL_PACK_ALIGNMENT,1) ; 
    glReadPixels(0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 
    NSData __autoreleasing *tempData = [NSData dataWithBytes:buffer length:1024*1024*4*sizeof(GLubyte)]; 
    [pageTextures addObject:tempData]; 
    if ([pageTextures count] > 5) { 
     [pageTextures removeObjectAtIndex:0]; 
    } 
    free((GLubyte*)buffer); 
    } 
} 

而最後一種方法:

-(void)attemptInstantPageTextureCapture { 
    if ([pageTextures count] > 0) { 
     self.page.texture.textureData = [pageTextures lastObject]; 
     self.page.lastLineId = [NSNumber numberWithInt:self.pageController.newLineId - 1]; 
     [self.pageController saveNotebookWithUndo:FALSE]; 
    } 
    [pageTextures removeAllObjects]; 
    pageTextures = [NSMutableArray arrayWithCapacity:0]; 
} 

我的問題是與NSData的* TempData的變量。出於某種原因,其中一個在我的PageView消失後會隨機掛起(通過Allocations Instruments發現)。

如果我加載PageView,則觸發captureInitialLinesTexture。然後,我可以在每個筆畫後添加大量的筆畫和capturePageTexture火,在NSMutableArray名稱的pageTextures中保留多達5個NSData變量。當我離開PageView時,NSMutableArray被清空。

現在,這裏是它在哪裏得到頭撞牆。 NSData的分配總是相同的大小,在這種情況下爲4mb。當頁面加載時,我有1個4mb的分配。如果我做筆畫,我可以多達5個。然後,當我離開PageView時,最多可以釋放5個4mb分配(NSData),但我總是留下1個。如果我隨後轉到樂器上的Call Tree,它會隨機地從第一個方法或第二個方法方法。爲什麼轉儲存儲在數組中的5個NSData沒有問題,但是出於某種原因,1個NSData在某處仍處於活動狀態。而且,這個神祕的NSData來自任意一種方法。

就像我說的,我已經搜索和搜索,無法找到解決這個問題的方法。 4MB的內存顯然是巨大的,所以任何此類泄漏都會隨着時間的推移殺死應用程序。

分配從一個嘗試: Allocation from one attempt

調用樹是嘗試: Call tree for that attempt

分配的另一種嘗試: Allocation for another attempt

調用樹其他嘗試: Call Tree for other attempt

每次都會觸發相同的確切代碼,並且每次它是隨機的哪個NSData保持活着。任何人有任何想法我做錯了什麼?如果您想知道,「頁面」和「紋理數據」變量是NSManagedObjects。至於事情我已經嘗試:

上NSData的對象ALLOC然後調用initWithBytes:長度:

initWithBytesNoCopy:長度: - 未調用free((GLubyte *)緩衝區); ((GLubyte *)緩衝區);長度:freeWhenDone: - 沒有呼叫空閒((GLubyte *)緩衝區);

不使用@autoreleasepool

上述兩種嘗試

NSData的類方法版本

不使用__autoreleasing用於VAR聲明

使的NSMutableArray pageTextures網頁瀏覽

的設定網頁瀏覽到屬性

零之前它從彈出導航控制器堆棧

使用__strong遍歷pageTextures可變數組並將所有NSData設置爲nil或null。

如上所述,這一切都發生在PageView類中,該類是PageViewController中的一種,它被推入並從彈出的導航控制器中刪除。一旦PageViewController(PageView的唯一超級視圖)彈出導航堆棧,一個隨機的NSData分配仍然存在。

任何建議都將非常感激!就上述核心數據元素而言,代碼完全按照計劃工作。唯一的問題是,鬼鬼祟祟的現場NSData分配...... :(

回答

4

解決了問題,但想到我會發布發生的情況,以防其他人有相同的問題。基本上問題是, NSData對象分配給核心數據實體和核心數據是在控制何時釋放自己的內存。因此,雖然代碼看起來很好,但是核心數據仍然保留在NSData對象上,在它們超出範圍並且運行循環完成之後(當ARC將正常踢入時)。

爲了解決這個問題,我們將NSData保存到一個文件中,並更改了模型,以便核心數據實體只包含文件路徑(NSString)而不是布爾數據(NSData)的字符串。

問題解決了:)時,不管它分配一個線程在另一個釋放

0

__autoreleasing關鍵字不會做你認爲它做的事情,它用於傳遞包含未初始化指針的指針來初始化它們的方法。那麼就知道不保留它們初始化的值,因爲它只是爲了返回被調用方法而使用的唯一目的。在這種情況下,你不需要它(默認的strong會很好,它會在發佈時釋放當你刪除那個關鍵字時,錯誤是否完全一樣?

+0

是的,刪除__autoreleasing沒有效果。同樣的問題仍然存在。但是,感謝您在關鍵字上點亮一些燈光。 – Kevin

+0

使用儀器,您應該能夠打印獲取對象的分配,保留和發佈歷史記錄,如下所示 - > http://www.markj.net/iphone-memory-debug-nszombie/看看你是否能夠得到信息,因爲它應該有很大幫助。 – borrrden

1

malloc不自由。把你的代碼包裝在這裏:

dispatch_async(dispatch_get_main_queue(), ^{ 
    // malloc and whatever other code goes here... 
});