Как узнать, когда объекту отправлено сообщение об освобождении? - PullRequest
1 голос
/ 03 июня 2009

Я работаю через несколько хитрый сбой iPhone, и похоже, виновником является преждевременный выпуск NSString. Я включил NSZombiesEnabled и вижу, что NSString - это зомби во время аварии. Однако я не могу определить, когда объект освобождается / освобождается - я прочесал свой код, просматривая сообщения об освобождении, отправляемые этому объекту, и установил точки останова в этих точках, но они не попадают в цель.

Я предполагаю, что это может быть проблема с многопоточностью или автоматическим выпуском, учитывая ее прерывистую природу, но есть ли способ подключиться к среде выполнения target-c через отладчик Xcode, чтобы сообщить точную точку, где объект освобождается? Или есть лучший способ диагностировать эту проблему?

Ответы [ 5 ]

5 голосов
/ 04 июня 2009

Если вы можете воспроизвести сбой в симуляторе, вы можете рассмотреть возможность использования инструмента malloc_history. (У него есть справочная страница.) Вам необходимо установить некоторые переменные среды: я обычно устанавливаю их через экран «Редактировать активный исполняемый файл» на панели «Аргументы», а затем использую флажки для их включения / выключения. Убедитесь, что вы отключили их перед отладкой на устройстве; если включено, программа попытается записать в /tmp, что песочница не позволяет.

Я считаю, что этот инструмент в сочетании с NSZombie позволяет мне отслеживать ошибки alloc / premature-release / access-after-dealloc. Как только NSZombie сообщает о доступе к освобожденному объекту, вы можете использовать malloc_history, чтобы определить, когда объект был выделен. Это обычно ставит меня на путь решения проблемы.

Еще один инструмент, который я нашел бесценным, - clang из проекта LLVM. Он все еще находится в разработке, но они регулярно выпускают двоичные файлы для MacOS-X, которые кажутся мне достаточно стабильными. В частности, он понимает политику управления памятью Какао. Использовать его так же просто, как:

% cd ${DIRECTORY_CONTAINING_XCODE_PROJECT}
% xcodebuild clean
% scan-build -V xcodebuild

Это сделает полную сборку вашего проекта и создаст отчет со списком любых очевидных ошибок (включая ошибки подсчета ссылок), которые обнаружит инструмент.

4 голосов
/ 03 июня 2009

Я, возможно, не думаю, что правильно, но вы рассматривали возможность добавления релиза и dealloc в свой класс

- (void) release 
{
  NSLog(@"Releasing");
  [super release];
}
- (void) dealloc
{
  NSLog(@"Deallocating");
  [super dealloc];
}

Включив комментарий Бена Готоу об использовании категории obj-c, вы получите следующее:

@interface NSString (release) 
  -(void) release;
@end

@implementation NSString (release)
-(void) release
{
  NSLog(@"NSString Released!");
  [super release];
}
@end
2 голосов
/ 15 декабря 2009

Еще один способ сделать это. Обязательно включите NSZombie, чтобы он сообщал адрес памяти объекта, который получает дополнительную версию. Затем запустите с Performance Tool-> Object Allocations. Это поднимет инструменты. Посмотрите журнал консоли, предоставленный организатором Xcode. Как только вы получите сбой, ищите адрес памяти в приборах. Вы увидите всю историю mallocs / освобождения для этого объекта, а также ссылки прямо в ваш код.

2 голосов
/ 03 июня 2009

вы могли бы сказать objc провайдеру dtrace, чтобы он вызывал ваш зонд всякий раз, когда вызывается -[NSString release], но это повлечет за собой небольшую неприятную попытку. NSStrings на самом деле не являются NSStrings, а являются подклассами, потому что класс реализован как кластер классов. Теперь, это не будет мешать нам; будет то, что NSString не имеет своего -release :-). Вы можете указать свое в категории.

В качестве альтернативы, если вам легко сказать, какой экземпляр NSString сломается, вы можете просто установить условную точку останова на -[NSObject dealloc] с помощью self==myInstance.

0 голосов
/ 03 июня 2009

Не могли бы вы реализовать dealloc () и поставить там точку останова? Глядя на трассировку стека с этой точки, вы узнаете, где и как она выпускается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...