4

編集:私はこのクラッシュの原因を見つけました!bbumは、バッファオーバーフローがこれの非常に一般的な原因であると指摘したので、私が持っていた唯一のバッファタイプmallocを調べました。

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

後で、配列の境界を超えてデータを上書きしていました。境界は、よりもはるかに大きいはずですbaseCells.count。ありがとうございます!

質問:EXC_BAD_ACCESS -drain中に 再現可能なものがNSAutoreleasePoolあります。これは、オブジェクトを過剰にリリースしていることを示しているようです。だから私は有効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
4

1 に答える 1

16

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

シミュレーターではなくデバイスでクラッシュが発生することも、メモリの破損を示しています。デバイス [ARM] とシミュレータ [i386] のアーキテクチャはまったく異なり、さまざまな問題が発生している可能性があります。

通常、それほど一貫して現れることはありません。

まず、クラッシュのバックトレースを投稿します。それは役立つかもしれません。

第二に、生の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ポインター (インスタンスのクラスを指すオブジェクト内の最初のポインターのバイト数) が踏みにじられました。これは通常、オブジェクトの前の割り当てでメモリのバッファーをオーバーランした場合に発生します。ほんの数バイトのオーバーランである場合、異なるプラットフォーム間の動作は異なる可能性があります。これは、malloc クォンタ (割り当ての実際のサイズ) (あるプラットフォームで 90 バイトを要求すると、96 を取得する可能性があるためです。別のプラットフォームでは 128 です) - - プラットフォーム間、さらにはリリース間でも異なります。

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

関数の 1 つに数フレームの深さでクラッシュが見られるobjc_msgSend*()場合は常に、メモリの破損である可能性が高く、そうであれば、ほとんどの場合、バッファ オーバーフローです。

簡単に実行できるので、ゾンビ検出でテスト パスを実行して、「実際には単にリリースしすぎている場合がある」ことを検出することをお勧めします。

于 2011-01-31T07:20:56.557 に答える