Подтвердить что ты не робот

Объект, созданный внутри области, освобожденный даже при использовании вне области видимости

Обновление: Это было исправлено в iOS 6.1 DP3 SDK.

Я выследил сбой при использовании после ARC, используя конфигурацию сборки по умолчанию (отладка, похоже, работает нормально). Проблема возникает при создании объекта внутри if-scope с непостоянным условием, присваивая его переменной извне области, а затем ссылается только на переменную с помощью массива 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

Как я прокомментировал в коде, он отлично работает, если obj ссылается каким-то другим способом, например, с помощью NSLog или с помощью NSArray. Я неправильно понял, как объекты выпущены с ARC и областями или это ошибка оптимизации в LLVM или Clang?

Я использую Xcode 4.5.2 с clang версии 4.1 (теги/Apple/clang-421.11.66) (на основе LLVM 3.1svn). Я могу воспроизвести его при создании для 64-разрядного x86 для iOS-симулятора и Mac OS X, и я уверен, что такая же проблема возникает при создании ARM, поскольку проблема была впервые обнаружена при запуске выпуска на iPhone.

Я опубликовал отчет об ошибке Apple и создал открытый радарный отчет.

Что, если что-нибудь, мне не хватает?

Обновить, сделал еще несколько экспериментов:

Как сказал Габро, компилятор переводит @[] в оператор [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.

4b9b3361

Ответ 1

Я только что протестировал следующий код как для OSX (x86 64), так и для iOS Simulator, и я не могу воспроизвести ошибку

 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 (теги/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

РЕДАКТИРОВАТЬ 2 Как указано в комментариях, можно воспроизвести ошибку, повышающую уровень оптимизации над -O0. Подведение итогов:

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

программа работает как ожидалось

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

появляется ошибка, представленная в вопросе. Это верно при любом уровне оптимизации над -O0

Это определенно ошибка в компиляторе.

Ответ 2

Вы ничего не пропустили. Это ошибка компилятора.