2011-01-31 12 views
4

EDIT:このクラッシュの原因が見つかりました! bbumは、バッファオーバーフローは、このために非常に一般的な原因であることを指摘したので、私は私が持っていた唯一のバッファ型のmallocを見て:オーバーリリースオブジェクトのデバッグ、NSZombieの問題

closedList = (AINavigationCell **)malloc(baseCells.count * sizeof(AINavigationCell *)); 

私は後でよりもはるかに大きくなっている必要があり、配列の境界を、過去のデータを上書きしましたbaseCells.count。ありがとう、あなた!

質問: 私はオブジェクトの上に放出していたことを示すように思わNSAutoreleasePool - ドレイン、中に再現可能EXC_BAD_ACCESSを持っています。だから私はNSZombieを有効にしますが、プログラムはそれ以上クラッシュしません。また、コンソールに情報を記録することもできません。 NSZombieをオフにすると、クラッシュが戻ってきます。これの意味は何ですか?私はNSZombiesがこの種の問題にまさに対処するために使われたと考えました。 NSZombieが助けにならない場合、このオーバーリリースされたオブジェクトを調べる別の方法がありますか?

また、シミュレータでクラッシュを再現できないため、NSZombieでInstrumentsを使用することができません。

フォローは、クラッシュポイントでのバックトレースです。

#0 0x31ac8bc8 in _cache_fill() 
#1 0x31acaf8e in lookUpMethod() 
#2 0x31ac8780 in _class_lookupMethodAndLoadCache() 
#3 0x31ac859a in objc_msgSendSuper_uncached() 
#4 0x328014f0 in -[__NSArrayReverseEnumerator dealloc]() 
#5 0x327b1f7a in -[NSObject(NSObject) release]() 
#6 0x327b63c8 in CFRelease() 
#7 0x327b58de in _CFAutoreleasePoolPop() 
#8 0x320e132c in NSPopAutoreleasePool() 
#9 0x30899048 in CAPopAutoreleasePool() 
#10 0x30902784 in CA::Display::DisplayLink::dispatch() 
#11 0x309027ea in CA::Display::IOMFBDisplayLink::callback() 
#12 0x30076bfa in IOMobileFramebufferVsyncNotifyFunc() 
#13 0x333dee6a in IODispatchCalloutFromCFMessage() 
#14 0x327e8be6 in __CFMachPortPerform() 
#15 0x327e06fe in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__() 
#16 0x327e06c2 in __CFRunLoopDoSource1() 
#17 0x327d2f7c in __CFRunLoopRun() 
#18 0x327d2c86 in CFRunLoopRunSpecific() 
#19 0x327d2b8e in CFRunLoopRunInMode() 
#20 0x3094a4aa in GSEventRunModal() 
#21 0x3094a556 in GSEventRun() 
#22 0x32c14328 in -[UIApplication _run]() 
#23 0x32c11e92 in UIApplicationMain() 
#24 0x00002556 in main (argc=1, argv=0x2fdff660) at /Users/hyn/Desktop/MyProject-trunk/main.m:14 

答えて

16

問題は2つのうちの1つになる可能性があります。オブジェクトが過剰にリリースされているか、メモリが壊れている可能性があります。メモリを破壊すると、オブジェクトの最初の数バイトが破損します。具体的には、自動解放プールのドレイン(または他のメッセージ)の間にクラッシュとして簡単に現れます。

シミュレータではなくデバイスでクラッシュが発生すると、メモリの破損が指摘されます。デバイス[ARM]とシミュレータ[i386]のアーキテクチャは大きく異なり、さまざまな問題があります。

通常、それは非常に一貫して現れません。

まず、クラッシュのバックトレースを投稿します。それは助けるかもしれない。

第2に、生のmallocコールは何ですか?またはバッファにデータを書き込む?このようなクラッシュの最も一般的な原因は、バッファの終わりを過ぎて実行されています。クラッシュ・トレースは、メモリ破損の古典署名されていることを

-


#0 0x31ac8bc8 in _cache_fill() 
#1 0x31acaf8e in lookUpMethod() 
#2 0x31ac8780 in _class_lookupMethodAndLoadCache() 
#3 0x31ac859a in objc_msgSendSuper_uncached() 
#4 0x328014f0 in -[__NSArrayReverseEnumerator dealloc]() 

(アーカイブするためのOPは問題を修正するが、後に上記を添加しました)。つまり、isaポインタ(インスタンスのクラスを指しているオブジェクトの最初のポインタのバイト数)が踏み込まれました。これは通常、オブジェクトがより前に割り当てバッファでオーバーランすると発生します。単なる2バイトオーバランであれば、異なるプラットフォーム間の振る舞いは異なるかもしれませんが、mallocの量 - 割り当ての実際のサイズ(1つのプラットフォームで90バイトを求め、96を得るかもしれません。 - プラットフォーム間、リリース間でも異なります。

特に、ランタイムがガベージ値を逆参照したポインタのように見える値でisaが踏み込まれ、その結果の場所をクラスのメソッドテーブルとして扱おうとしました。

objc_msgSend*()関数の1つに数フレーム深いクラッシュが発生すると、メモリ破損が発生する可能性が高くなります。その場合、ほとんど常にバッファオーバーフローになります。

これは簡単なことですので、ゾンビ検出を使ってテストパスを実行して「時には実際にはリリースされているケース」をキャッチするのは良い考えです。

+1

あなたの提案は大丈夫でした。バッファオーバーフローの問題がありました。あなたは時間を節約しました。多分デバッグの日数を節約しました。そして、私は存在しなかった超過リースについて懸命に探していました。どうもありがとうございます。 – Morrowless

+0

あなたは大歓迎です。 – bbum

+0

bbumデモンストレーションは素晴らしいですが、もう一度! :-) – Dad