Objective-C связанные объекты утечки под ARC

Я столкнулся со странным objc_setAssociatedObject поведение под ARC. Рассмотрим следующий код:

static char ASSOC_KEY;

@interface DeallocTester : NSObject
@end

@implementation DeallocTester
- (void) dealloc
{
    NSLog(@"DeallocTester deallocated");
    //objc_setAssociatedObject(self, &ASSOC_KEY, nil, OBJC_ASSOCIATION_RETAIN);
}
@end

@implementation AppDelegate
- (void) applicationDidFinishLaunching:(UIApplication *)application
{
    NSObject *test = [[DeallocTester alloc] init];
    objc_setAssociatedObject(test, &ASSOC_KEY, [[DeallocTester alloc] init],
                             OBJC_ASSOCIATION_RETAIN);
}

Я создаю экземпляр DeallocTesterтогда я поставил другую DeallocTester как связанный объект для него, то оба они выходят из области видимости.

Я ожидаю -dealloc первого объекта, который будет вызван, затем связанный объект, который будет освобожден, но я вижу "DeallocTester deallocated" сообщение печатается только один раз. Если я раскомментирую objc_setAssociatedObject линия в -dealloc, второй объект также освобождается.

Ссылка Objective C указывает, что связанные объекты автоматически освобождаются после уничтожения объекта. Это компилятор /ARC/ любой другой вопрос или я что-то упустил?

Обновить

Этот пример кода на самом деле работает, если вы запускаете его из совершенно нового проекта. Но у меня есть два проекта с поддержкой ARC, где этого нет. Я сделаю небольшое исследование и предоставлю лучший образец.

Обновление 2

Я заполнил rdar://10636309, Утечка связанных объектов, если объекты NSZombie включены в проекте с поддержкой ARC

2 ответа

Решение

Я нашел источник проблемы - у меня было NSZombie объекты включены в обоих моих проектах, где эта ошибка появляется.

Насколько я понимаю, когда объекты зомби включены, нормальные экземпляры заменяются на NSZombie после освобождения, но все связанные объекты остаются в живых! Остерегайтесь такого поведения!

Я создал rdar://10636309

Обновление: есть обходной путь Cédric Luthi, и эта проблема, кажется, исправлена ​​в iOS 6.

Код, который вы разместили, работает точно так же, как рекламируется в ARC. Я переписал твой dealloc реализация, чтобы помочь сделать вещи немного более очевидными.

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

Вот итоговый журнал:

2012-01-03 06:49:39.754 ARC  Stuff[47819:10103] deallocating <DeallocTester: 0x6878800>
2012-01-03 06:49:39.756 ARC  Stuff[47819:10103] deallocating <DeallocTester: 0x688b630>

Вы уверены, что компилируете с включенным ARC?

Другие вопросы по тегам