Я работаю над преобразованием основанного на документах приложения из сборки мусора (оно отлично работало под 10.6) в автоматический подсчет ссылок (пытаясь заставить его скомпилировать и запустить для 10.12). Я получаю постоянный EXC_BAD_ACCESS, когда последнее окно закрыто. Статический анализатор ничего не помечает.
Я использовал инструменты для поиска зомби, и действительно, кажется, что освобожденному объекту отправлено сообщение release
. Вот след:
# Event ∆ RefCt Timestamp Responsible Library/Responsible Caller
173 Release -1 3 00:05.226.677 Foundation __48-[NSFileAccessArbiterProxy removeFilePresenter:]_block_invoke
174 Release -1 2 00:05.226.679 Foundation -[NSFilePresenterXPCMessenger invalidate]
175 Retain +1 3 00:05.226.823 Foundation -[NSBlockOperation initWithBlock:]
176 Retain +1 4 00:05.226.858 AppKit -[NSDocument close]
177 Release -1 3 00:05.227.350 Foundation -[NSFilePresenterXPCMessenger dealloc]
Retain/Release (2) 00:05.227.484 AppKit -[NSDocumentController removeDocument:]
180 Release -1 2 00:05.227.485 AppKit -[NSDocumentController removeDocument:]
Retain/Release (2) 00:05.227.496 AppKit -[NSUIActivityManager addProvider:toUserActivity:withSetter:]
183 Autorelease 00:05.227.499 AppKit -[NSWindowController _windowDidClose]
184 Release -1 1 00:05.228.172 Foundation -[NSAutoreleasePool drain]
185 Release -1 0 00:05.228.184 Foundation -[NSBlockOperation dealloc]
186 Zombie -1 00:05.242.579 AppKit -[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed:saveWindows:]
Трудность, с которой я сталкиваюсь при диагностике этой проблемы, заключается в том, что я вижу сообщение, отправляемое зомби, но поскольку я не выпускаю никаких объектов (все это делается с помощью ARC), я предполагаю, что происходит неявное освобождение. где-то. Но я не уверен, где искать.
В отладчике lldb
жалуется на сбой в main.m
по адресу:
return NSApplicationMain(argc, (const char **) argv);
Любая помощь будет принята с благодарностью. Спасибо.
После дополнительных исследований проблема все еще не решена, но у меня есть подсказка:
Благодарю за ваш ответ. Да, на данный момент я предполагаю, что это проблема управления памятью. Есть ли способ найти преступника? Не похоже, чтобы использование Zombies in Instruments помогало: оно указывает на проблему, но не помогает мне решить проблему. То есть оскорбительная строка в соответствии с инструментами выглядит так: «-[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed:saveWindows:]»; но я никогда не выпускал эту строку. Я сделал то, что может быть небольшим прогрессом в выяснении вещей.
Структура, которую я использую в документе:
NSDocumentController
: по умолчанию, без подкласса NSDocument
: подкласс, MyDocument; также делегат окна NSWindowController
: по умолчанию, не подкласс NSWindow
: MyDocument.xib
, MainMenu.xib
Я попытался установить делегат открытого окна на ноль следующим образом:
-(void)windowWillClose:(NSNotification *)notification
{
windowOpen = YES;
NSArray *windowControllers = [self windowControllers];
NSWindowController *currentWindowController = [windowControllers firstObject];
NSWindow *windowForCurrentController = [currentWindowController window];
NSDocument *w = [windowForCurrentController delegate];
[windowForCurrentController setDelegate:nil];
}
Это вызывает тот же сбой.
Затем я подумал, что, возможно, currentWindowController (или приложение) отправляет сообщения освобожденному окну. Поэтому я попытался добавить строку (в конце метода выше):
[currentWindowController setWindow:nil];
Это избавляет от сбоев, но создает новые проблемы (например, при попытке загрузить новые файлы и т. д.). Но мне интересно, является ли это ключом к решению общей проблемы.