13

更新:これは iOS 6.1 DP3 SDK で修正されました。

デフォルトのリリース ビルド構成を使用して ARC でビルドすると、use-after-deallocated クラッシュが発生することを突き止めました (デバッグは正常に機能しているようです)。この問題は、非定数条件で if スコープ内にオブジェクトを作成し、それをスコープ外から変数に割り当ててから、Objective-C 配列または辞書リテラルを使用してのみ変数を参照するときに発生します。

これは、私が見つけた再現可能な最小のケースです。

void test(BOOL arg)
{
    id obj = nil;

    if (arg) {
        obj = [NSObject new];
    }

    // obj already deallocated here
    @[obj];

    // but using NSArray works
    //[NSArray arrayWithObject:obj];

    // @[obj] works if obj is referenced i.e. by NSLog print out
    //NSLog(@"%@", obj);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        test(YES);
    }
    return 0;
}

ゾンビ オブジェクトを有効にしてこれをビルドして実行すると、次のエラー メッセージが表示されます。

-[NSObject retain]: message sent to deallocated instance 0x100109100

コードでコメントしたように、 withまたは using insteadobjのように、他の方法で参照されている場合は正常に動作します。オブジェクトが ARC とスコープでどのように解放されるかを誤解していますか、それとも LLVM または Clang の最適化バグですか?NSLogNSArray

Xcode 4.5.2 を clang バージョン 4.1 (tags/Apple/clang-421.11.66) (LLVM 3.1svn ベース) で使用しています。iOS シミュレーターおよび Mac OS X 用の x86 64 ビット用にビルドするときに再現できます。iPhone でリリース ビルドを実行したときに問題が最初に見つかったのと同じ問題が、ARM 用にビルドするときに発生することは間違いありません。

Apple にバグ レポートを提出し、オープン レーダー レポートを作成しました。

もしあれば、何が欠けていますか?

更新、さらにいくつかの実験を行いました:

Gabro が指摘したように、コンパイラはステートメントに変換される@[]ため、[NSArray arrayWithObjects:count:]いくつかのテストを行いました。

// works
id a[] = {obj};
[NSArray arrayWithObjects:a count:1];

// does not work
const id *b = (id[]){obj};
[NSArray arrayWithObjects:b count:1];

// does not work
[NSArray arrayWithObjects:(id[]){obj} count:1];

私の推測では、これは ARC と無名 C 配列を組み合わせたときに発生します。

4

2 に答える 2

1

あなたは何も見逃していません。コンパイラのバグです。

于 2012-12-03T19:51:44.670 に答える
1

OSX (x86 64) と iOS シミュレーターのビルドの両方で次のコードをテストしましたが、バグを再現できません。

 void test(BOOL arg) {
     id obj = nil;

    if (arg) {
        obj = [NSObject new];
    }
    @[obj];
    NSLog(@"Hi there");
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        test(YES);
    }
    return 0;
}

上記のコードは、単にHi thereコンソールに出力して戻ります。

私の構成はあなたのものと同じです:コンパイラとしてXCode 4.5.2とAppleのclangバージョン4.1(tags/Apple/clang-421.11.66)(LLVM 3.1svnに基づく)。

編集

また、コマンドラインからコンパイルしようとしました(#include <Foundation/Foundation.h> 上記の例の冒頭に追加した後)

clang -fobjc-arc -framework Foundation main.m

そしてまた結果は

2012-12-03 12:47:45.647 a.out[39421:707] Hi there

EDIT 2 コメントで指摘されているように、最適化レベルを-O0. 要約:

clang -O0 -fobjc-arc -framework Foundation main.m

プログラムは期待どおりに動作します

clang -O1 -fobjc-arc -framework Foundation main.m

質問で提示されたバグが表示されます。これは、どの最適化レベルを超えても当てはまります。-O0

これは間違いなくコンパイラのバグです。

于 2012-12-03T18:37:19.020 に答える