2013-08-23 18 views
10

私が書いたプロセス中に、私のアプリケーションはメモリが上昇していて、それをリリースしていないようです。iOS [ARC]アプリがメモリを解放していません

私が言及したいと思いますまず最初は、私が書いたものの基本的なアウトラインがこのであるということです:
- (NSDataの-initWithContentsOfURLを使用してデータをフェッチ)URLをリクエスト
- NSDictionarysのNSArrayのにNSDataのを解析NSJSONSerialization + JSONObjectWithStream
使用 - アプリケーションは、上記を行い

復号データをFMDBフレームワークを使用して、SQLiteのデータベース内のレコードを削除/デコードNSArrayの挿入/更新をループする、しかし、それは、未決定の期間のループでそれをしませんこのアプリケーションでは、「読み込み中の」HUDが表示されます。私はそれが言及する価値があるかもしれないと思っていましたが、それが正しく解放されていればメモリの使用に影響を与えてはならないので、何回このプロセスを何回行うのかは重要ではありません。私がここに間違っているなら、私に助言してください。

私のコードはうまく動作しますが、それは意図したとおりです。しかし、私がアプリケーションコードをプロファイルすると、メモリはちょうど上昇し続けるようです。それはセグメント全体で落ちますが、全体的にそれは上昇し続けています(IEは以前に使用したものを完全にリリースしません)。

私は前述の通り、割り当て、リーク、VMトラッカーを使用してアプリケーションをプロファイリングし、トレースハイライトを使用しました。

トレースハイライト:メモリ使用量が徐々に上がっていくが、いくつかのメモリ(すべてではない)プロセスは、高い使用率に達すると終了します十分な長メモリに対して実行されている場合は意味を落としていることを示します。

割り当て:OKと思われます。割り当てにはスパイクがありますが、いつ始めるかはいつも元に戻ります。

(約10分間放置)VMトラッカーを私はheapshotsを取り、彼らは常に、セグメントごとに最大500〜700キロバイトを残しドロップダウン:メモリが一貫上昇していることを示すために証明し、かつ微量で発見として(フルメモリーを解放していませんハイライト)。レジデントは本当に高いやっている

リーク:それは私が実際に持っていることは注目に値します
enter image description here enter image description here

:ここ

は、いくつかの割り当て/ VMトラッカーランニングのスクリーンショットのアプリケーションが見つかりませんリーク試みました:
- 自動リリースツールの追加
- 各プロパティを割り当てることによって "強制解放"。 NSURL、NSRequestsなどのような、 nilの

私の質問に:
- 私はメモリを解放するために特別な何かをするべきか?
- どうすればこの問題をさらにデバッグできますか?
- インストゥルメントが私に与えるデータから何が間違っているかを知るにはどうすればよいですか?

---- EDIT: ----
はここでデータをフェッチする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; 
    } 

} 

上記のメソッドは、アプリケーション代理人のwhileループ内から呼び出されます。前述のように、whileループは未定の長さです。

--- EDIT 2:---

次は(FMDBを使用してSQLiteデータベースを更新)@finally文の中に何が起こるかです。私のクラスには、テーブルごとに1つのメソッドがたくさんあります。それらはすべて最初のものから重複していると彼らはすべて、しかし同じパターンに従います。

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

autoreleasepoolsが、それは厄介なことがありますが、コード:

-(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方法であり、もともとこれらを持っていなかった。改善があるかどうかを確認するために、さまざまな場所で実装しました(なかった)。

--- EDIT 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

Iは、(代わりにファイルに格納)のNSDataをつかむためASIHTTPRequestを使用して問題を減少させました。上記の改訂コードをご覧ください。しかし、問題はまだ解決しています。 質問、もともと1として


- このアプリのプロセスの第二の部分に何か問題はありますか?

+1

+1すてきな質問。しかし、いくつかのコードを含める必要があります。 –

+2

スタック割り当てを使用して、新しい割り当てが実際に何であるか確認しましたか? runloopに走る機会を与えていますか? (長いループをより小さな操作に分割し、NSOperationQueueで処理することを検討してください)。 – bneely

+0

URLリクエストを送信して配列に分解する実際のコードを含めました。 – Joshua

答えて

1

iOSでARCを使用するtry/catchを使用すると、メモリリークが発生する可能性があり、回避することをお勧めします。

代替アプローチは、非同期NSURLConnection、またはNSURLConnectionをNSURLConnectionと同期させて使用することです。

+0

非常に真実。それは悲しいことだが真実だ。 – Sulthan

+0

この例では、try/catchがリークを引き起こしていません。これは、この問題に気づいた後でtry catchが実装されたためです。非同期NSURLConnectionも使用されましたが、非同期処理が完了するまで主スレッドがブロックされていたため、同期に変更されました。 NExtステップは、私が今日やっているNSOperationの使用状況をチェックアウトし、結果をポストバックします。 – Joshua

+0

その場合、requestAndParseメソッドがリークを引き起こしていますか? – Ronan

関連する問題