0

次のコマンドでリークを呼び出すと、次のmallocスタックトレースがあります。

MallocStackLogging=1リーク

リーク:0x15d3cac0サイズ= 256ゾーン:DefaultMallocZone_0x7b0a000

Call stack: [thread 0xb0468000]: | thread_start | _pthread_start | __NSThread__main__ | -[NSThread main] | -[AggregatorObjCWorkQueue newThreadMainLoop] | -[NSRunLoop(NSRunLoop) runMode:beforeDate:] | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSources0 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ | __NSThreadPerformPerform | -[NSObject performSelector:withObject:] | -[AggregatorTask run] | -[ComAppAggregatorApiSystemClientWorkerFactory_$4_$1 run] | -[ComAppAggregatorFrameworkClientSubscriptionSyncer startWithComAppAggregatorApiClient:] | -[ComAppAggregatorSyncClientSyncSubscriptionRegistry addSubscriptionWithComAppAggregatorQueryQueryXML_Subscription:] | -[ComAppAggregatorSyncClientSyncSubscriptionRegistry newSyncAndPostWithComAppAggregatorQueryQueryXML_QueryKey:] | -[ComAppAggregatorSyncClientSyncSubscriptionRegistry writeUpdateWithComAppAggregatorQueryQueryXML_QueryKey:] | -[ComAppAggregatorSyncClientSyncSubscriptionRegistry writeSubscriptions] | -[JavaUtilTreeMap putWithId:withId:] TreeMap.m:371 | -[JavaUtilTreeMap createNodeWithId:withId:] TreeMap.m:634 | -[JavaUtilTreeMap_Node init] TreeMap.m:1463 | -[IOSObjectArray initWithLength:type:] IOSObjectArray.m:42 | calloc | malloc_zone_calloc

誰かがmallocからのこのコールスタックトレースを理解するのを手伝ってもらえますか?つまり、質問を分解するには:1.スタックトレースはどのように順序付けられていますか?Class1 Method1 | Class2 Method2 | Class3 Method3:これらは何を意味しますか?

2:オブジェクトの説明の前の正と負の符号はどういう意味ですか?-[クラスメソッド]| +[クラスメソッド]

3:これらのうち、実際にリークしたのはどれですか?スタックトレースのどのオブジェクト/部分がリークしているかを正確に特定できません。

ドキュメントへのリンクは素晴らしいでしょう!

4

1 に答える 1

5

(Instrumentsアプリで)Leaks Instrumentを使用して、ExtendedDetailペインでスタックトレースを確認する方がはるかに簡単です。

ただし、スタックトレースを分析する方法は次のとおりです。まず、のすべてのインスタンスを|改行に置き換えます。

Call stack: [thread 0xb0468000]: 
thread_start 
_pthread_start 
__NSThread__main__ 
-[NSThread main] 
-[AggregatorObjCWorkQueue newThreadMainLoop] 
-[NSRunLoop(NSRunLoop) runMode:beforeDate:] 
CFRunLoopRunInMode 
CFRunLoopRunSpecific 
__CFRunLoopRun 
__CFRunLoopDoSources0 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ 
__NSThreadPerformPerform 
-[NSObject performSelector:withObject:] 
-[AggregatorTask run] 
-[ComAppAggregatorApiSystemClientWorkerFactory_$4_$1 run] 
-[ComAppAggregatorFrameworkClientSubscriptionSyncer startWithComAppAggregatorApiClient:] 
-[ComAppAggregatorSyncClientSyncSubscriptionRegistry addSubscriptionWithComAppAggregatorQueryQueryXML_Subscription:] 
-[ComAppAggregatorSyncClientSyncSubscriptionRegistry newSyncAndPostWithComAppAggregatorQueryQueryXML_QueryKey:] 
-[ComAppAggregatorSyncClientSyncSubscriptionRegistry writeUpdateWithComAppAggregatorQueryQueryXML_QueryKey:] 
-[ComAppAggregatorSyncClientSyncSubscriptionRegistry writeSubscriptions] 
-[JavaUtilTreeMap putWithId:withId:] TreeMap.m:371 
-[JavaUtilTreeMap createNodeWithId:withId:] TreeMap.m:634 
-[JavaUtilTreeMap_Node init] TreeMap.m:1463 
-[IOSObjectArray initWithLength:type:] IOSObjectArray.m:42 
calloc 
malloc_zone_calloc

質問1:最も古いスタックフレームが上にあり、最も若いものが下にあります。いわゆる、と呼ばれるthread_start、と呼ばれる、など。_pthread_start__NSThread__main__-[NSThread main]

質問2:指定された関数は、クラス-[NSThread main]のインスタンスメソッドを実装する関数です。Objective-Cコンパイラは、ソースコードで文字通り書き出すことができない名前(のような)を持つ関数を生成できます。mainNSThread-[NSThread main]

+クラスメソッドの場合、関数名は。ではなくで始まります-。したがって、のクラスメソッドallocは。NSObjectという名前の関数によって実装され+[NSObject alloc]ます。

質問3:投稿したスタックトレースは、リークされたオブジェクトが割り当てられた時点のスタックトレースを示しています。そのスタックトレースのどの部分も、必ずしも「実際にリークしたもの」ではありません。

オブジェクトがリークすることの意味を理解する必要があります。これは、リークされたオブジェクトを指す、またはリークされたオブジェクトを指すオブジェクトを指す、またはリークされたオブジェクトを指すオブジェクトを指すオブジェクトを指すグローバル変数またはローカル変数(スタック上)がないことを意味します。 、などなどなど。グローバル変数またはローカル変数(ビジネスで言う「ルートポインタ」)から始まり、リークされたオブジェクトにつながるポインタのチェーンがないため、プログラムはにアクセスする方法がありません。オブジェクトはまだ割り当てられていますが。

では、なぜそれがリークされたのですか?ルートポインタからオブジェクトへの最後のチェーンが壊れる前にリリースされなかったためです。呼び出されるべき関数であるリリース関数が呼び出されなかったため、リークが発生しました。オブジェクトが割り当てられてからしばらくすると呼び出されるはずです。リークツールは、オブジェクトが割り当てられたときのスタックトレースのみを表示するため、欠落しているリリースをどこに配置するかを判断するのに十分な情報が得られない場合があります。

これで、InstrumentsアプリのLeaksインスツルメントに戻ります。Leaksインストゥルメントは、リリースすべき正確な場所を表示することもできませんが、オブジェクトが保持、リリース、および自動リリースされるたびのスタックトレースを表示することはできます。これらの追加のスタックトレースは、オブジェクトがリークされた理由を理解するのに役立つ場合があります。また、Instrumentsは、リークコマンドラインツールよりも適切にスタックトレースをフォーマットします。また、リークされたオブジェクトのネットワークがある場合、Instrumentsはそのネットワークをグラフィカルに表示できるため、アプリがオブジェクトをリークしている理由を簡単に理解できる可能性があります。

Appleはたくさんの開発者向けビデオを投稿しており、そのうちのいくつかはInstrumentsを紹介しています。どのビデオがリーク検出について話しているのか正確には思い出せませんが、少なくとも1つは知っています。WWDC 2012のビデオから始めて、戻ってください。

編集

WWDC2012のビデオ「Session409-LearningInstruments」では、約35分でLeaksインスツルメントの使用について説明しています。

WWDC2011のビデオ「Session310-What'sNewIn Instruments」では、約39分でLeaksインスツルメントの使用について説明しています。

それは他のいくつかでも間違いなく言及されています。

于 2012-11-15T07:15:15.610 に答える