0

私は既存の大規模なコードベースに取り組んでおり、iOS SDKを4.1にアップグレードした後、非常に奇妙な動作が見られます。問題の核心は、割り当てられなくなる特定のクラスのように見えます-obj_msgSendに不正なアクセスをスローしており、実際にはNULLではありませんが、objc_msgSendが気に入らないスタック上のClassオブジェクトのようです。

元の失敗した行は次のようになりました:-

tileProjection = [[RMFractalTileProjection alloc] initFromProjection:proj tileSideLength:sideLength maxZoom:18];

問題を切り分けるためにこれを分解しました:-

RMFractalTileProjection *p = [RMFractalTileProjection alloc];  // <- this crashes
p = [p initFromProjection:proj tileSideLength:sideLength maxZoom:18];
tileProjection = p;

それから私はこれを試しました:-

Class c = NSClassFromString(@"RMFractalTileProjection");
assert(c);
NSLog( @"RMFractalTileProjection class(ptr) %p", c );  // <- prints an address OK
NSLog( @"RMFractalTileProjection class(obj) %@", c );  // <- crashes

デバッガーでは、Classオブジェクトは適切であるように見えますが、印刷しようとするとNSLogがクラッシュします。

注意すべき点の1つは、問題のクラスが次のように宣言されていることです。プロトコルが問題を引き起こしているかどうかはわかりません。この特定の部分はオープンソースコードの大きな塊であるため、このプロトコル要件を削除して、それが違いを生むかどうかを確認することは非常に困難です。

@interface RMFractalTileProjection : NSObject<RMMercatorToTileProjection>
{
 ...
}

これに関するどんな助けも大いに感謝します-それはショーストッパーです。

ありがとう

4

3 に答える 3

1

これは実際には答えではありませんが、前進するためのいくつかのアイデアです。

現時点で頭に浮かぶ唯一の原因は、メモリの破損とある種のリンクの問題です。おそらく、クラスの2つのバージョンを何らかの方法でリンクしているのでしょう。

これがクラスであると仮定すると、allocでクラッシュさせるのに問題はないようです。+initializeなどはありません。

私が自分自身に問いかけ、答えようとしている質問は次のとおりです。

クラスの名前を変更するとどうなりますか?

別の名前で新しい同一のクラスを作成するとどうなりますか?

obj_msgSendに渡されるポインター:それは合理的ですか?クラスのように見えるものを指していますか?

クラスをサブクラス化し、サブクラスで初期化を使用しますか?

ポインタは常に同じですか?もしそうなら、それが何を指しているかを見て、実行中に変化するかどうかを確認できます。

クラスに自分を送るとどうなりますか?

于 2010-09-16T13:39:34.183 に答える
1

OK、ついにこれを見つけました。ジェレミーが示唆したように、これは通常の記憶の踏み台であることが判明しました。

私が見つけた難しさは、踏みつけられたのはClassオブジェクト自体ではなく、クラスのメタクラス構造でした。これは通常のClassオブジェクトですが、クラス'isa'ポインターによって参照される1つ上のレベルです。そのため、デバッガーでクラスを調べたところ、クラスは問題ないように見えました。これを見つけるには、isaポインターをたどり、1つのレベルでメモリをダンプする必要があります。私にとって幸運なことに、このクラスはNSObjectのサブクラスにすぎませんでした。深くサブクラス化されていれば、これを見つけるのははるかに困難でした。弾丸を噛み、objc_msgSendをリバースエンジニアリングし、スタックフレームにあるものを正確に調べ、すべてのポインターをたどった後、最初の手がかりを得ました。うん、難しい方法:)

Matt Gallagharの投稿(およびリンクをたどって見つけた他のさまざまな投稿)は、この迷路を通り抜けるのに非常に役立ちました-みんなありがとう!

これには多くの時間を費やしましたが、良い面として、私は過去1日半の間にObjectiveCの内部について多くのことを学びました:)

于 2010-09-17T11:22:13.300 に答える
0

これらの提案に感謝しますJeremyP-一日中キーボードに頭をぶつけた後、新鮮な提案をするのはいつでも良いことです!

同じ名前で同じクラスを作成するというあなたの提案は、問題を解決したようです。理由がわからないので、ここで何が起こっているのかを理解する必要があると感じています。確かに、ある種のリンカーの問題のように聞こえますが、何がこのような深刻なランタイムエラーを引き起こし、ビルド時に警告を生成することすらできないのか、私にはまだわかりません。

再。ポインタ、それは合理的に見えますが、クラス内の何かは最終的にobjc_msgSend内のnullポインタとして逆参照されます。時折、コードを変更して再構築した後、代わりにnullポインターを取得します。この振る舞いは明らかに、記憶の踏みつけのような非決定論的な何かを示唆しています。

調査結果を投稿します。

于 2010-09-16T19:57:06.290 に答える