2013-11-22 43 views
0

我不太熟悉Objective-C,所以請原諒我,如果這是一個愚蠢的問題。我創建了一個後臺線程來解析目錄中存在的文件列表,目錄中的文件可以隨時更改。iOS - 調用contentsOfDirectoryAtPath在循環中泄漏內存

我呼籲在循環的每次迭代「contentsOfDirectoryAtPath」,我突然分配去了300MB。我無法弄清楚如何讓ARC釋放返回的數組。有人可能會指出我在這裏的正確方向嗎?你可以看到,我試圖通過設置'files'釋放數組爲零,但它不起作用。

+0

你使用ARC項目嗎? – Joey

+0

請注意:[NSFileManager defaultManager]不是線程安全的,請改用[[NSFileManager alloc] init]。 – San

+0

@San我會閱讀[文檔](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/nsfilemanager_Class/Reference/Reference.html#//apple_ref/doc/uid/20000305-SW19),然後再進行索賠。 – CodaFi

回答

1

你怎麼創建這個線程? NSThread? NSOperation和NSOperationQueue? GCD?

對於NSThread和的NSOperation,你應該創建自己的自動釋放池設置線程的一部分。這樣臨時對象在該線程內得到正確管理。

我相信GCD會爲您處理這些細節。

在Objective C中的新版本(目標C 2.0,我相信),你應該使用新的語法

@autoreleasepool 
{ 
    //Code to use a local autorelease pool 
} 

對於生成一噸的臨時對象的循環,你可以創建任何一個地方自動釋放池代碼塊。你可以重構你的代碼是這樣的:(從而釋放在該迭代創建的臨時對象)

while(1) 
{ 
    @autoreleasepool 
    { 
    NSArray *files = [nfm contentsOfDirectoryAtPath:dataDir error:nil]; 
    /* 
    if(files == nil) 
     break; 

    if([files count] <= 0) 
    { 
     files = nil; 
     [NSThread sleepForTimeInterval: 5.0f]; 
     continue; 
    } 

    if(![ViewController obtainLock]) 
    { 
     files = nil; 
     continue; 
    } 
    */ 
    //[ViewController releaseLock]; 
    files = nil; 
    } 
} 

這會導致它以創建循環的每個迭代一個新的自動釋放池,並在最後排幹

順便說一句,如果你使用NSThread,不要。學習如何使用GCD代替。 GCD(Grand Central Dispatch)比NSThread更有效地利用系統資源。 NSThread基於POSIX線程,這些線程創建起來非常昂貴,並且在應用程序的生命週期中將設備上的物理內存綁定在一起。

NSOperationQueues在最近的OS版本被重構使用GCD在幕後,所以他們也同樣有效的內部,雖然難比GCD使用的大部分事情。

+0

謝謝你的答案,添加一個自動釋放池做的伎倆。我正在使用NSThread創建此線程。你說NSThread在應用程序的生命週期中佔用了物理內存,但是如果這個線程應該運行在應用程序的生命週期,這真的很重要嗎?無論哪種情況,我都會看看GCD--感謝指針! – Gogeta70

0

那麼,我認爲答案顯而易見。看看documentation

許多程序創建的自動釋放臨時對象。這些 對象將添加到程序的內存佔用空間直到 塊的末尾。在許多情況下,允許臨時對象累積 ,直到當前事件循環迭代結束時,不會導致 過多的開銷;但是,在某些情況下,您可能會創建大量的臨時對象,這些臨時對象會大大增加內存佔用量,並且希望更快地處理這些對象。在這些 後面的情況下,您可以創建自己的自動釋放池塊。在塊的末尾 處,釋放臨時對象,這通常會導致它們的釋放,從而減少程序的內存佔用量 。

而你可以看到這個question

因此,解決方案使用您的@autoreleasepool{},因爲您正在創建許多臨時對象。