我正致力于将基于文档的应用程序从垃圾收集(在10.6下运行正常)转换为自动引用计数(试图让它编译并运行10.12)。我在最后一个窗口关闭时得到一致的EXC_BAD_ACCESS。静态分析器没有标记任何内容。
我使用Instruments查找Zombies,实际上似乎有一条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正在帮助它:它指出了一个问题,但并没有帮助我解决问题。也就是说,根据Instruments的违规行似乎是" - [NSApplication(NSWindowCache)_checkForTerminateAfterLastWindowClosed:saveWindows:]&#34 ;;但我从来没有发过那条线。我已经做了一些可能会有点进展的事情。
我在文档中使用的结构是:
NSDocumentController
:默认,不是子类
NSDocument
:子类,MyDocument;也是窗口的代表
NSWindowController
:默认,不是子类
NSWindow
:MyDocument.xib
,MainMenu.xib
我尝试将打开窗口的委托设置为nil,如下所示:
-(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];
这消除了崩溃,但引入了新问题(例如在尝试加载新文件时等)。但我想知道这是否是帮助解决整体问题的线索。
答案 0 :(得分:0)
问题是app委托设置为MyDocument
(NSDocument
子类)。通过创建标准AppDelegate
类(NSObject
,实现NSApplicationDelegate
协议),在XIB中创建相应的NSObject
并将其设置为{{1}来解决问题然后将AppDelegate
作为AppDelegate
的委托。
我似乎问题的根源是MyDocument
对象被解除分配,但它仍然是MyDocument
子类的委托。然后NSWindow
向委托发送了一封dealloc消息,但它已被解除分配,导致崩溃。