2015-04-21 61 views
0

正如你可以看到,下面的心不是代碼做多(全部註釋掉)比不過列舉了一組文件,更多的,我的內存使用量增長超過2 GB 40後運行通過按下UI上的按鈕啓動的功能的秒數。內存泄漏 - 與ARC目標C啓用

我可以運行UI幾個小時,在按下按鈕之前,內存使用量不會超過8MB。

鑑於ARC打開了,內存是什麼?

removed original code as the edit below made no differance.

編輯:

嘗試的是@autoreleasepool{ dispatch_asyny ... }和排列周圍,同時與while循環這是沒有效果的內部。

這裏是添加autorelasepool代碼和清理

-(void) search{ 

    self.dict = [[NSMutableDictionary alloc] init]; 
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/SeaWall.log"]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSString *bundleRoot = @"/"; 
     NSFileManager *manager = [NSFileManager defaultManager]; 
     NSDirectoryEnumerator *direnum = [manager enumeratorAtPath:bundleRoot]; 
     NSString *filename; 

     while ((filename = [NSString stringWithFormat:@"/%@", [direnum nextObject]]) && !self.exit) { 
      @autoreleasepool { 

       NSString *ext = filename.pathExtension; 

       if ([ext hasSuffix:@"so"] || [ext hasSuffix:@"dylib"]) { 
        if (filename == nil || [NSURL URLWithString:filename] == nil) { 
         continue; 
        } 

        NSData *nsData = [NSData dataWithContentsOfFile:filename]; 
        if (nsData != nil){ 
         NSString *str = [nsData MD5]; 
         nsData = nil; 

         [self writeToLogFile:[NSString stringWithFormat:@"%@ - %@", [filename lastPathComponent], str]]; 

        } 
       } 
       ext = nil; 
      } // end autoreleasepool 
     } 
     [fileHandle closeFile]; 
     [self ControlButtonAction:nil]; 


    }); 
} 

Memory Usage

回答

2

內存是不完全泄露:這是很願意被釋放,但它永遠不會有機會成爲。

ARC建立在Objective-C的手動內存管理規則之上。基本規則是「調用init的對象/函數擁有新實例」,並且所有者不再需要該對象時,該對象必須爲release

這是創建對象的簡便方法的問題,例如[NSData dataWithContentsOfFile:]。該規則意味着NSData類擁有該實例,因爲它在其上調用了init。一旦該值被返回,該類將不再需要該對象,並且需要釋放該對象。但是,如果在被調用者有機會保留該實例之前發生這種情況,那麼在發生任何事情之前它就會消失。

爲了解決這個問題,Cocoa引入了autorelease方法。此方法將對象的所有權轉移到最後設置的自動釋放池。自動釋放池在退出其範圍時會「排空」。

可可/ AppKit的/自動的UIKit周圍設置事件處理程序自動釋放池,所以你一般不需要擔心。但是,如果您有一個長期運行的方法,則會成爲問題。

可以使用@autoreleasepool語句聲明一個自動釋放池:

@autoreleasepool 
{ 
    // code here 
} 

在閉幕式支架,通過自動釋放池收集的對象被釋放(並可能重新分配的,如果沒有其他人給他們一個參考)。

所以,你需要換你的循環體在此聲明。

下面是一個例子。此代碼「泄漏」大約10兆字節每秒我的電腦上,因爲執行永遠不會離開@autoreleasepool範圍:

int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool 
    { 
     while (true) 
     { 
      NSString* path = [NSString stringWithFormat:@"%s", argv[0]]; 
      [NSData dataWithContentsOfFile:path]; 
     } 
    } 
} 

在另一方面,與此相關,內存使用率保持穩定,因爲執行離開@autoreleasepool範圍在每次循環的末尾:

int main(int argc, const char * argv[]) 
{ 
    while (true) 
    { 
     @autoreleasepool 
     { 
      NSString* path = [NSString stringWithFormat:@"%s", argv[0]]; 
      [NSData dataWithContentsOfFile:path]; 
     } 
    } 
} 

在循環條件創建對象是尷尬的長期循環,因爲這些都不是由內@autoreleasepool回升。您還需要在@autoreleasepool範圍內獲取這些內容。

+0

不知道你的循環體是什麼意思。所以我嘗試了以下方法:圍繞'dispatch_async'執行任何操作。在'dispatch_async'裏面,並且封閉了一切也沒做的事。在while循環周圍,它也沒有做什麼。 – Cripto

+0

@Cripto它需要在循環中。循環體是'while'行後括號內的代碼。 – zneak

+0

請看看我的編輯。它似乎沒有按預期工作。謝謝 – Cripto

0

內存需要由自動釋放池釋放。 否則它會鎖定,因爲你正在經歷,它會泄漏。

在你的循環放:

@autoreleasepool { /* BODY */ }