Objective-C связанные объекты утечки под ARC - PullRequest
9 голосов
/ 03 января 2012

Я столкнулся со странным поведением 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 ]

9 голосов
/ 03 января 2012

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

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

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

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

1 голос
/ 03 января 2012

Код, который вы разместили, работает точно так же, как рекламируется в 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?

...