Как определить, находится ли объект в NSAutoreleasePool
Я хотел бы знать, сколько раз объект был автоматически выпущен. Я использовал цель c достаточно долго, чтобы узнать, был ли объект автоматически освобожден или нет, как правило, довольно просто, однако я постоянно вижу вопросы, связанные с памятью, и сохраняю количество. В какой-то момент ответ всегда заканчивается: "Вы не можете доверять retainCount объекта" - с этим я согласен, НО, если бы вы могли определить, сколько раз объект был автоматически выпущен, тогда вы действительно могли бы доверять retainCount, если добавили категория как:
@interface NSObject (NSObject_MemoryDebugging)
- (NSUInteger) autoReleaseCount;
- (NSUInteger) retainCountWithAutoRelease;
@end
@implementation]
/** Determine how many times this object has been marked for autorelease **/
- (NSUInteger) autoReleaseCount;
{
// ??? not sure how to figure this out.
return 0;
}
- (NSUInteger) retainCountWithAutoRelease
{
NSUInteger retainCount = [self retainCount];
NSUInteger autoReleaseCount = [self getAutoReleaseCount]; // ???
return retainCount - autoReleaseCount;
}
@end
Все еще будет исключение для неизменяемых типов, поскольку они обычно увеличивают количество сохраняемых файлов во время копирования, поэтому вы по-прежнему не можете доверять retainCount для них.
Что я НЕ предлагаю
Я не ищу этот ответ, чтобы использовать retainCount в производственном коде. Тем не менее, я вижу, что это полезно для устранения проблем с памятью.
Я полагаю, что некоторые люди будут ненавидеть этот вопрос, так как программистам не нужно заботиться о том, сколько раз объект был выпущен автоматически. Кодирование должно быть связано с балансировкой ассигнований, сохранением, копированием, новым с выпуском, окончанием истории. Тем не менее, смысл этого в том, чтобы помочь людям, стучащим головой. [NSObject retainCount]
сжигает много людей, и ответ на этот вопрос будет довольно крутым.
Я уверен, что есть способ определить, сколько раз объект был автоматически выпущен. Я просто не знаю, что это, отсюда вопрос.
Смотрите аналогичный вопрос: Объекты внутри NSAutoreleasePool в target-c.
редактировать
Спасибо всем за ваши ответы. Вы можете найти это интересным => Ариэль отметил, что реализация Какао в GNUStep и, в частности, NSAutoReleasePool имеет такой метод: + (NSUInteger) autoreleaseCountForObject: (id) anObject. Этот метод медленный и возвращает только счет автоматического выпуска из NSAutoReleasePools в потоке вызывающих. Тем не менее... Интересно, что его там. В документах говорится, что это действительно полезно только для отладки. Это действительно то, что я надеялся найти (или найти возможным) в рамках Какао как-то.
Я согласен с ответами, данными, что даже если бы можно было рассчитать автелизу, что существуют лучшие инструменты (зомби, утечки, статический анализатор).
4 ответа
Во-первых, вам придется иметь дело с несколькими пулами автоматического выпуска и объектом, который автоматически освобождается более одного раза, возможно, в нескольких пулах.
Во-вторых, это не (просто) NSAutoreleasePool
это делает -retainCount
ненадежный. Проблема в том, что всевозможные объекты, как ваши, так и Apple, сохраняют вещи по разным причинам, самые неизвестные для вас. Даже с учетом автоматического выпуска, ваши объекты часто не будут иметь ожидаемого количества сохраняемых данных, потому что за кадром что-то наблюдает или временно помещает их в словарь и т. Д.
Лучшие способы устранения проблем с памятью - это инструмент Leaks, NSZombie и статический анализатор.
Нет, нет общедоступного API для определения того, был ли объект автоматически освобожден.
Даже если бы это было общедоступно, ваш -retainCountWithAutoRelease
Метод будет иметь некоторые проблемы:
Объект может быть помещен несколько раз в один и тот же пул автоматического выпуска, поэтому вам потребуется счетчик автоматического выпуска для одного пула автоматического выпуска вместо флага, указывающего, был ли объект автоматически освобожден;
Из-за многопоточности объект может быть помещен в несколько пулов авто-релиза, поэтому вам потребуется счетчик авто-релизов, охватывающий несколько пулов авто-выпуска;
Из-за многопоточности вам нужно будет синхронизировать код с обработкой Cocoa счетчиков хранения и пулов автоматического выпуска, а внутренняя блокировка, используемая Cocoa, не видна приложениям.
NSAutoreleasePool действительно имеет +(void)showPools
метод, о котором я раньше совершенно не подозревал. Это может быть полезно. Также см. Есть ли способ проверить объекты NSAutoreleasePool?, В этой теме KennyTM сказал (в комментарии):
Ну, так как содержимое печатается в stderr, вы можете открыть поток и проанализировать его, чтобы получить все указатели
Для справки, я использовал class-dump для платформы Foundation, чтобы увидеть детали NSAutoreleasePool, и он имел следующее:
@interface NSAutoreleasePool : NSObject {
void *_token;
void *_reserved3;
void *_reserved2;
void *_reserved;
}
+ (void)addObject:(id)arg1;
+ (id)allocWithZone:(struct _NSZone *)arg1;
+ (void)showPools;
+ (void)releaseAllPools;
+ (unsigned int)autoreleasedObjectCount;
+ (unsigned int)topAutoreleasePoolCount;
+ (BOOL)autoreleasePoolExists;
+ (void)enableRelease:(BOOL)arg1;
+ (void)enableFreedObjectCheck:(BOOL)arg1;
+ (unsigned int)poolCountHighWaterMark;
+ (void)setPoolCountHighWaterMark:(unsigned int)arg1;
+ (unsigned int)poolCountHighWaterResolution;
+ (void)setPoolCountHighWaterResolution:(unsigned int)arg1;
+ (unsigned int)totalAutoreleasedObjects;
+ (void)resetTotalAutoreleasedObjects;
- (id)init;
- (void)drain;
- (oneway void)release;
- (id)initWithCapacity:(unsigned int)arg1;
- (void)addObject:(id)arg1;
- (id)retain;
- (unsigned int)retainCount;
- (id)autorelease;
- (void)dealloc;
@end
Я добавил это в качестве ответа, так как он казался скорее ответом, чем более подробным в вопросе, который я задал.
Похоже, вам нужно переопределить -(id)autorelease;
метод как работа по добавлению объекта в NSAutoreleasePool
сделано там.
Что-то вроде того:
-(id)autorelease{
_isAutoreleased = YES; //some BOOL member initialized to NO and returned on -(BOOL)isAutoreleased;
[NSAutoreleasePool addObject:self];
return self;
}
Также посмотрите на эту ссылку