前文; これは、「リークのある巨大なアプリを持っています」という一般的な質問ではありません。これは、完全なソース コードを使用したほぼ自明なデモ アプリで自動参照カウントが適切に機能しないか、微妙なコード生成またはコンパイラの問題、または Instruments のバグのいずれかに関する特定の問題です。(TLDR: ああ。実際には奇妙な小さな競合状態です)
Instrumentsの「割り当て」リストにインスタンスリークが表示されているという事実に混乱していますが、そのクラスのインスタンスは1つしかなく、ARCがdeallocメソッドを呼び出しており、それが呼び出されていることがわかっています。解放が完了すると出力される NSLog メッセージがありますが、Instruments のリークのリストにはまだ表示されます。
保持カウントが 1 を超えることはありません。誰にも保持されておらず、dealloc されていますが、Instrument のリークでアクティブなインスタンスとして表示されるため、「リーク」のように見えます。
そんなことがあるものか?
私はまだ ARC で Objective-C を学んでいるので、よくある初心者の間違いを犯しているに違いないと思います。これが私の唯一のinitと私のオブジェクトのdeallocです:
- (id) initWithMessage:(NSString*)messageForUser
{
self = [super init];
if (self)
{
_message = messageForUser;
NSLog( @"from constructor: %@",_message);
}
return self;
}
- (void)dealloc {
NSLog(@"Goodbye cruel world. One WPMyObject signing off.");
// [message release]; // ARC forbiddeth thee! Begone release.
_message = nil;
// [super dealloc]; // ARC forbiddeth explicit super dealloc
}
できるかどうかを確認するため[super dealloc]
に、dealloc メソッドを呼び出そうとしましたが、ARC はエラーでユーザーをブロックしました。ただし、独自の init メソッドを作成すると、ブロックされません。
XCodeで「実行」を使用してプログラムを実行すると、「さようなら残酷な世界」NSLogメッセージが表示されます.メモリ リーク テンプレートを使用した Instruments 分析が使用されている場合は、次のように実行します。
以下のインスタンス作成コードなしで実行すると、標準ライブラリの malloc リークがいくつか報告されるだけですが、このコードを追加すると、すべてのリークが発生します。
WPMyObject * myObject = [[WPMyObject alloc] initWithMessage: @"Hello World!\n" ];
これが私が見ているものであり、WPMyObjectの唯一のインスタンスがリークしていることを理解していると思います:
非常に簡単な完全なソース コード (Objective-C と を使用した小さな Mac OS X コマンド ライン アプリFoundation/Foundation.h
) は BitBucket にあります。このリンクをクリックして、ブラウザでソース コードを表示します。
main.m ユニットは、@autoreleasepool {...}
コンテキスト ステートメント内で単一のテスト オブジェクト インスタンスの作成を実行します。
自分のコンピューターでまったく簡単なコードを見たい場合は、次のように取得します。
hg clone https://bitbucket.org/wpostma/objectivecplaymac
}
更新:自動解放プールを終了する の直前に次のコード行を追加することで、「リーク」(Instruments のバグ、または clang/llvm コンパイラのバグであり、「実際のリーク」ではない可能性があります) を修正できます。
NSLog( @"Reached end of autorelease pool" );
うん。ログメッセージを追加。「漏れ」が消えます。これは Mac OS X 10.7.5 上の XCode 4.5.2 (4G2008a) で、Instruments バージョン 4.5 (ビルド 4523) が含まれています。
Update2: これは単純なマルチプロセスの競合状態です。以下のコードは、妥当なデバッグ ビルドのハッカーのようです。「Instruments が処理を完了するまで待ってから、main() を終了する」というより明確な方法があれば、Apple エンジニアの将来の優れた機能になる可能性があります。PROFILER_SYNC("MESSAGE") マクロは、リリース モードでは何も展開されませんが、デバッグ ビルドでは "MESSAGE" をプロファイラーに送信します。これは非常に便利です。
int main(int argc, const char * argv[])
{
// This creates and cleans up an auto-release pool context.
@autoreleasepool {
foo(); // Microscopic amounts of debug code you want profiler to analyze go here.
#ifdef DEBUG
usleep(10000); // race condition prevention in debug builds, so Instruments can finish up.
#endif
}
#ifdef DEBUG
usleep(10000); // race condition prevention in debug builds, so Instruments can finish up.
#endif
return 0;
}