2013-08-23 66 views
10

我的應用程序在我寫入的過程中,在內存中上升,似乎不會釋放它。iOS [ARC]應用程序不釋放內存

我想提的第一件事情是,我已經寫了什麼的基本輪廓是這樣的:
- 一個網址(取使用NSData的-initWithContentsOfURL數據)
- 解析的NSData到NSDictionarys的NSArray的使用NSJSONSerialization + JSONObjectWithStream
- 迴路通過解碼NSArray的插入/更新/使用FMDB框架與所述數據刪除記錄在SQLite數據庫解碼

的應用程序執行的上方,但是它確實它在一個循環爲未確定期間的時間,其中應用程序顯示一個「加載」平視顯示器。我認爲可能值得一提的是,雖然我發現它在這個過程中執行的次數是微不足道的,因爲如果它正確釋放,它不會影響內存使用量。如果我在這裏錯了,請告訴我。

我的代碼運行良好,它完成了它的目的。但是,當我剖析應用程序代碼時,內存似乎還在不斷上升。它在整個領域都有所下降,但整體而言仍然在不斷上升(IE並未完全釋放它之前使用的)。

如前所述,我已使用Allocations,Leaks,VM Tracker和Trace Trace Highlights來描述應用程序。

跟蹤亮點:顯示內存使用量逐漸上升,但是在丟棄一些內存(不是全部),這意味着,如果該進程正在運行足夠長的時間內存將達到高使用率和終止。

分配:似乎沒問題。分配有高峯,但總是回落到開始的地方。我把heapshots,他們總是下拉留下每段最大500-700kb(左約10分鐘)

VM跟蹤:證明顯示,內存持續上升,並沒有完全釋放內存(如跟蹤發現強調)。居民似乎得到真正的高

泄漏:沒有在應用程序中發現泄漏

這裏的分配/ VM跟蹤運行的一些截圖:
enter image description here enter image description here

值得一提的是,其實我已嘗試:
- 添加autoreleasepools
- 「強制釋放」通過分配每個屬性;如NSURL,NSRequests等;以零

我的問題:
- 我應該做一些特別的東西來釋放內存?
- 我該如何進一步調試此問題?
- 我如何才能最清楚地發現樂器給我的數據有什麼問題?

---- 編輯: ----
下面是發送URL請求獲取數據的代碼。:

- (void) requestAndParse : (NSString *)url 
{ 
    NSURL *theURL; 
    ASIHTTPRequest *request; 
    NSData *collectedData; 
    NSError *error; 
    @try { 
        // File cache the NSData 
        theURL = [[NSURL alloc] initWithString: url]; 
        request = [ASIHTTPRequest requestWithURL: theURL]; 
        [request setDownloadDestinationPath: [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]]; 
        [request startSynchronous]; 
        [request waitUntilFinished]; 

        collectedData = [[NSData alloc] initWithContentsOfFile:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]]; 


        if ([collectedData length] > 0) { 
         records = [NSJSONSerialization JSONObjectWithData:collectedData options:NSJSONReadingMutableContainers error:&error]; 
        } 

    } 
    @catch (NSException *exception) { 

        // Failed 
        NSLog(@"Parse error: %@", error); 

    } 
    @finally { 

        // DB updates with the records here 
        ... 

        // remove file 
        [[NSFileManager defaultManager] removeItemAtPath:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"] error:nil]; 
        // release properties used 
        collectedData = nil; 
        request = nil; 
        theURL = nil; 
    } 

} 

上述方法在Application Delegate的while循環中被調用。如前所述,while循環的長度不確定。

---編輯2:---

以下是@finally聲明(更新使用FMDB SQLite數據庫)中會發生什麼。我班有很多這樣的方法,每個表都有一個。他們都遵循相同的模式,雖然,因爲它們都是從第一個重複:

-(BOOL) insertBatchOfRecords:(NSArray *)records { 

__block BOOL queueReturned = YES; 

@autoreleasepool { 

    FMDatabaseQueue *dbQueue = [self instantiateDatabaseQueue]; 
    [dbQueue inTransaction:^(FMDatabase *tdb, BOOL *rollback) { 
     if (![tdb open]) { 
      NSLog(@"Couldn't open DB inside Transaction"); 
      queueReturned = NO; 
      *rollback = YES; 
      return; 
     } 

     for (NSDictionary *record in records) { 
      [tdb executeUpdate:@"INSERT OR REPLACE INTO table (attr1, attr2) VALUES (?,?)", [record valueForKey:@"attr1"], [record valueForKey:@"attr2"]]; 

      if ([tdb hadError]) { 
       queueReturned = NO; 
       *rollback = YES; 
       NSLog(@"Failed to insert records because %@", [tdb lastErrorMessage]); 
       return; 
      } 
     } 
    }]; 

    [dbQueue close]; 
    dbQueue = nil; 

} 

return queueReturned; 
} 

,遵循的是-instantiateDatabaseQueue方法:

-(FMDatabaseQueue *) instantiateDatabaseQueue { 
@autoreleasepool { 
    return [FMDatabaseQueue databaseQueueWithPath: [self.getDocumentsDirectory stringByAppendingPathComponent:@"localdb.db"]]; 
} 
} 

的autoreleasepools可能使凌亂,但代碼原本沒有這些。我在不同的地方實施它們,看看是否有任何改進(沒有)。

---編輯3 ---

我一直在分析應用程序在過去的幾天,仍然沒有找到答案沒有運氣。我已將相關應用程序的這一部分分離到它自己的單獨項目中,以確保它確實導致了內存使用。事實證明這是正確的,因爲應用程序的表現仍然相同。

我已經拍攝了更多的照片,並且仍然很難確定究竟是什麼錯誤。下面看到,分配看起來沒問題(VM對我來說看起來也不錯),並且仍然沒有泄漏(沒有圖片,因爲沒有!)

但是,當我在Trace亮點是,內存使用量不斷增加,直到達到太多使用量(3GS上大約70 + MB),然後由於使用了太多內存而崩潰。

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

我通過使用ASIHTTPRequest用於抓取NSData的(存儲到代替文件)降低的問題。請參閱上面的修改代碼。然而,問題仍然存在,只需要更長的時間發生!

按原來,問題
- 有什麼不對的應用程序的第二部分?

+1

+1不錯的第一個問題。不過,可能需要包含一些代碼。 – 2013-08-23 22:10:35

+2

你有沒有使用stackshots來查看新的分配實際上是什麼?你是否讓runloop有機會運行? (考慮將你的長循環分解爲更小的操作並使用NSOperationQueue處理它們)。 – bneely

+0

我已經提供了發送URL請求,將其分解成一個數組的實際代碼。 – Joshua

回答

1

在iOS中使用try/catch可能導致內存泄漏,最好避免。

另一種方法是使用異步NSURLConnection或具有同步NSURLConnection的NSOperation。

+0

非常真實。這很可悲,但卻是事實。 – Sulthan

+0

在這種情況下使用的try/catch不會導致泄漏,這一點我敢肯定,因爲以後我就注意到這個問題,嘗試捕捉被實施的。異步NSURLConnection也被使用,但它被改爲同步,因爲主線程被阻塞直到異步完成。 NExt的步驟是檢查我今天要做的NSOperation用法,並將結果返回。 – Joshua

+0

在這種情況下,你確認requestAndParse方法導致了泄漏? – Ronan

相關問題