2009-09-05 23 views
13

アプリケーションの異なるビルドをしばらく再生していて、奇妙なことが起きているようです。カカオ64ビットバイナリリークメモリ? (NSDataを解放するとメモリが解放されません)

私のアプリのアイドルフットプリントは5メガバイトです。ファイルのアップロード時にファイルサイズのメモリが予約されます。アップロード後、予約されたメモリを解放する必要があります。

  • 32ビットのi386無GC::すべてのメモリが即座に解放され、今のビルド(GC =ガベージコレクタ)に違いがあります。
  • 32ビットi386 GC:ほぼすべてのメモリが即座に解放されます。残りの時間は後である。
  • 64bit x86_64 no-GC:最小限のメモリが解放されます。 like 10%
  • 64bit x86_64 GC:メモリが全く解放されません。メモリは何時間も予約されています。 (活動モン)

私はCLANGでLLVMを使っています。今日はいつも楽器を走っていて、リークやゾンビなどをチェックしていました。すべてがきれいであるようです。 (アプリはかなりシンプルです)

この現象の説明はありますか?


更新:

いくつかの奇妙なものです。私はこの問題を煮沸しました:

NSDataに20MBのファイルをロードしてリリースします。ガベージコレクションを有効にしないでこれをやっています。コードは:

NSData *bla = [[NSData alloc] initWithContentsOfFile:@"/bigshit"]; 
[bla release]; 

i386 32ビット用にビルドすると、20MBが割り当てられ、解放されます。ビルドを64bit x86_64に切り替えると、リリースは何もしません。 20MBの滞在が割り当てられます。

upper pic 32bit lower 64 http://kttns.org/zguxn

上位1が32ビットと下位1つの64ビットのために構築されていることを除いて2つのアプリの違いはありません。 GCが実行されていません。 (GCが表示され、同じ問題を有効にすると。)


アップデート2:私はapplicationDidFinishLaunchingで唯一の上側のコードで最初から新しいココアアプリを作成するときに

同じ動作を観察することができ:. 64ビットモードでは、メモリは解放されません。 i386は期待どおりに動作します。

同じ問題がNSDataではなくNSStringで表示されます。 64ビットカーネルをブートすると表示されます。 (起動時に64に保持される。)

OSは、ガベージコレクタは、必ずしも直ちにメモリを解放しない10.6.0

+0

NSDataインスタンスの割り当てを試して、割り当てを解除して、メモリそれらのいずれかが再生されていますか?メモリが不足していない限り、プログラムはメモリをOSに返さないことがあります。 – Amok

+0

私はこれを運のない10.6で再現しようとしました。 テストアプリにバグを報告しましたか? – Ken

+0

あなたのアプリは正しく動作しており、メモリが漏れていません。半詳細な説明については私の答えを参照してください。 – bbum

答えて

10

まず、インストゥルメントのオブジェクトグラフ計測器を使用して、メモリがもはや使用中ではないと考えられることを確認します。保持カウントまたは強い参照をどこかに持っていません。

これ以上使用されていない場合は、コレクタが気になるスレッショルドにヒットしていないため、メモリが不安定になります。しかし

、この文:

64ビットのx86_64の無GC:最小限のメモリが解放され です。 like 10%

私は注意します。具体的には、コードがnon-GCで動作するように設計されている場合(retain/releaseで)、(a)メモリリークがあり、CFRetainや何らかのグローバルキャッシュを使用している場合、GCや)あなたは正しいツールを使ってメモリリークがあるかどうかを判断していません。

あなたはどのようにしてメモリが漏れていると判断していますか?

更新;アクティビティモニターを使用してプロセスのRSIZE/VSIZEを監視しています。これは、 "時間が経つにつれて私のプロセスが成長する"ことを超えて、実際にあなたに何かを伝えることはありません。

ないより

より可能性が高い(私はソースを見ていない)、このコード:

NSData *bla = [[NSData alloc] initWithContentsOfFile:@"/bigpoop"]; 

は、20メガバイトのファイルをプロセスにでmmap() D」されることになります。 malloc()スタイルの割り当てはまったく必要ありません。代わりに、OSは20MBの連続したアドレス空間をプロセスに渡し、ファイルの内容をそのプロセスにマップします。 NSDataの内容を読んでいくうちに、ファイルにフォールト・ページが表示されます。

blaをリリースすると、マッピングは破棄されます。しかしそれは、VMサブシステムがアプリケーションのアドレス空間を20MB削減することを意味するものではありません。

したがって、実際のメモリではなく、アドレス空間の束を作成しています。あなたのプロセスは64ビットなので、アドレススペースはかなり無限のリソースであり、アドレスを使用するためのコストはほとんどないので、OSがこのように実装される理由です。

I.e.リークはなく、あなたのアプリは正常に動作している、GCかいいえ。

これはよくある誤解であり、したがって、star'dの質問です。

+0

私はメモリリーク機器を使用しています。そして、32ビットビルドとしては、すべてが期待通りに機能します。 – jsz

+0

元の質問への更新をお読みください。 – jsz

+0

答えに感謝します。それはあなたが正しいと思う:) – jsz

2

あります。

Objective-Cガベージコレクタの場合、ココアのガベージコレクタオブジェクトには、collectIfNeededというメッセージを送信して、コレクションを実行するのに適していることを示すメッセージ、またはcollectExhaustivelyを送信して、すべてのごみ(ただしこれは中断可能です)。 the docsを参照してください。

0

私はiPhoneOS 3.2に非常によく似た問題があり、メモリが再利用されているとは本当に思いません。私は自分の間違いを見落としている可能性は少しありますが、私は非常に徹底的でした。

NSKeyedUnarchiverのunarchiveObjectWithFile:を使用して、単一の大きなNSDataと別のはるかに小さいオブジェクトを含むカスタムオブジェクトを読み込みます。私のカスタムオブジェクトのdeallocメソッドが呼び出され、NSDataオブジェクトが解放され、直前のretainCount == 1になります。物理メモリは、NSDataサイズの一部ではなく、どんな量でもデクリメントされず、繰り返しメモリの警告が確実に生成されます。実際にレベル2の警告を受け取るまでテストします。

(GDB)P(INT:=リリース前に(

:リリース後

(GDB)P(INT)[(NSDataの*)pastItsWelcomeData retainCount]
$ 1 = 1

)[(NSData *)pastItsWelcomeData retainCount]
ターゲットがこのメッセージセレクタに応答しません

+0

あなたは別の問題があります。 GCはiPhoneには存在しません。また、retainCountはオブジェクトの生存時間の問題をデバッグするのに間違ったことです。代わりにインストゥルメントを使用してください。これは異なる問題の説明であり、質問に答えないので、別の質問として投稿する必要があります。 –

関連する問題