10

私はすでに次の問題についてレーダー (rdar://12311693、http ://openradar.appspot.com/12311693 ) を提出しましたが、誰かが間違いを見つけられるかどうかを確認するために、ここにも投稿すると思いました。クラッシュにつながる可能性のある私のコード。

次のコード サンプルは、コンパイラの最適化をオン (-Os) にしてビルドすると過剰リリースによりクラッシュしますが、コンパイラの最適化をオフ (-O0) にするとクラッシュしません。プロジェクトは Xcode 4.4.1 (4F1003)、Apple LLVM コンパイラ 4.0 でビルドされています。

num2 が過剰にリリースされると、アプリがクラッシュします。ゾンビ オブジェクトを有効にして、これが事実であることを確認します。

// This crashes under -Os, but not under -O0
NSNumber *num1 = @((float)arc4random() / (float)UINT32_MAX);
NSNumber *num2 = @((float)arc4random() / (float)UINT32_MAX);

NSNumber *foo1 = num1;
NSNumber *foo2 = num2;

for (NSUInteger i=0; i<2; i++) {

    NSLog(@"foo1: %p %@", foo1, foo1);
    NSLog(@"foo2: %p %@", foo2, foo2);

    // swap foo1 and foo2
    foo1 = num2;
    foo2 = num1;
}
4

1 に答える 1

6

コンパイラのバグ。提出していただきありがとうございます。

num1num2指し示されたインスタンスの寿命を保証する必要があります。オプティマイザーが [正しく] スタック スロットを再利用し、[誤って] 問題を引き起こすリリース/保持シーケンスを発行していると思われます。


スタックマスターへの対応。これはコンパイラのバグです。ARC の要点は、Objective-C をコンパイラが 100% 確実にコードを分析して、開発者であるあなたが保持/解放する必要がないように保持/解放する場所を知ることができるポイントに移行することです。概して、MRR の世界でオブジェクトを使用するすべてのコードが適切に動作し、開発者がオブジェクトを ARC の制御から「エスケープ」しない限り、スレッド化に直面しても正確にそれを達成できます。いたずらをする。2 つの大きな if がありますが、MRR を大幅に改善しています。

最後に、最適化されたときに (コンパイラのバグが発生していないときに) コードが機能しない場合、それはコードが壊れているためです。適切に作成されたオプティマイザーは、正しく作成されたコードを壊しません

一部のコンパイラはバグが多いことで有名ですが、LLVM はその 1 つではありません (GCC については何年も使用していないので主張しませんが、同じことが言えると思います)。iOS または OS X システムは、起動のたびに最適化を有効にしたコードを使用してコンパイルされた何百万もの行を実行し、システムは非常にうまく機能します。

したがって、いいえ、「オプティマイザーがオンになっている」ことは、クラッシュの最終的な解決策ではありません。


Catfish_man が指摘したように、意図的に技術的に正しくないコードを生成する難解なオプティマイザ オプションがあります。-Os またはその他の「標準」最適化では有効になりません。それらは主に数学演算に集中しているため、通常、計算にエラーが急速に忍び寄るほどクラッシュすることはありません。

于 2012-09-17T17:20:24.140 に答える