我正在编写一个Cocoa OpenGL应用程序并使用CVDisplayLink
每this technical note运行我的主循环。它适用于运行循环。
问题在于,有时当我退出时,我的应用程序已经退出后,我的显示链接回调将在其自己的线程上调用。一旦我调用任何OpenGL函数(在这种情况下为glClear
),这会导致我的渲染代码被调用并崩溃,因为我的上下文不再存在。
我的NSView的CVDisplayLinkRelease(displayLink);
函数中有dealloc
,但它似乎永远不会被调用,我假设因为ARC。有没有我可以确保我的显示链接在我的视图之前被销毁?
编辑:我没有注意到崩溃实际上是由我拥有的断言触发的。我在每次OpenGL调用后都在glGetError
断言,以确保我能及早发现错误。致电glClear
或[[view openGLContext] flushBuffer];
后,我收到错误1286,即GL_INVALID_FRAMEBUFFER_OPERATION
。
这具有逻辑意义,因为我的窗口和视图正在被释放,但它没有帮助解决问题。我不想忽略这些错误,因为它们显然可能发生在更多情况下,而不仅仅是这个。我仍然需要找到“正确”的方法来确保我的显示链接在我查看之前关闭。
答案 0 :(得分:2)
当应用程序终止时,其自动释放池中的任何内容都不会被释放 - 应用程序只需exit
,并让操作系统清理内存。由于没有任何内容被释放,因此没有任何内容收到dealloc
消息。
这意味着两件事:
有两种方法可以处理终止。我通常在单窗口应用程序中执行此操作的方法是让我的应用程序的委托不是别的,并直接拥有我的主窗口控制器。另一种方法是将自己添加为NSApplicationWillTerminate
通知的观察者,并通过例如停止显示链接来回复它。
如果清理的任何部分可能需要一些时间,那么您的应用程序代表应该通过返回applicationShouldTerminate:
来回复NSTerminateLater
,并且您应该在发送replyToApplicationShouldTerminate:
消息时发送该应用程序完成你需要做的任何事情。
原始问题的另一个解决方案 - 在您有机会关闭链接之前调用CVDisplayLink回调 - 完全相反:启用sudden termination。启用后,您的应用程序将通过发送自身SIGKILL
(命令行调用kill -9
更为熟知)退出,这意味着每个线程将停止立即
当然,如果你有任何确实需要清理的东西(锁定文件,网络连接等),那么你应该禁止突然终止那些事情的生命周期,并准备在那段时间内定期终止