В этом нет ничего странного, особенно если ваш NSWindowController
находится в пуле авто-релиза.
Объект (скажем, x
) освобождается, когда каждый объект, которому он принадлежит, освобождает его.Autorelease
является отложенным выпуском, то есть фактически не выпускается до тех пор, пока не будет истощен пул автоматического выпуска.
Рассмотрим следующую цепочку событий:
B creates x
A owns x
A autoreleases x. // x is not released; it's put on an autorelease pool
B releases x. // x is not dealloced yet, because x is not released by the autorelease pool
autorelease pool is drained. x is sent another release message. nobody owns x. x is dealloc'd.
Вот что вы видите.
--- Обновление ---
Еще,точно, таинственное использование пула автоматического выпуска возникает из вашей строки
[self.wc release];
При этом используется геттер wc
, то есть он вызывает [self wc]
.Теперь синтезированный метод получения по умолчанию реализован в этой части времени выполнения obj-c , в частности objc_getProperty_non_gc
.Обратите внимание, что ваша собственность (retain)
, то есть (atmomic retain)
.Чтобы гарантировать атомарность, получатель retain
получает ивар, а затем возвращает его после autorelease
его:
id *slot = (id*) ((char*)self + offset);
if (!atomic) return *slot;
// Atomic retain release world
spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)];
_spin_lock(slotlock);
id value = objc_retain(*slot);
_spin_unlock(slotlock);
// for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
return objc_autoreleaseReturnValue(value);
Вот почему он включен в пул авто-релиза.В любом случае,
obj.property=[[SomeClass alloc] init];
[obj.property release];
- плохая идея.В вашем случае self.ivar
во второй строке вернуло то, что вы назначили в первой строке, но это не гарантируется в случае умных несинтезированных средств доступа или в многопоточной среде.Когда вы делаете
obj.property=x;
id y=obj.property;
x
и y
, они могут различаться, если obj
выполняет какое-то умное кэширование, или если есть другой поток, обращающийся к obj
, который меняет obj.property
между двумя строками,Поэтому вместо этого используйте временную переменную:
SomeClass* a=[[SomeClass alloc] init];
obj.property=a;
[a release];