3

我正在编写一个 Cocoa OpenGL 应用程序并CVDisplayLink按照此技术说明运行我的主循环。它适用于运行循环。

问题是有时当我退出时,在我的应用程序已经退出后,我的显示链接回调将在它自己的线程上被调用。这会导致我的渲染代码在我调用任何 OpenGL 函数(glClear在本例中)时立即被调用并崩溃,因为我的上下文不再存在。

我有CVDisplayLinkRelease(displayLink);我的 NSView 的dealloc功能,但它似乎从未被调用,我假设是因为 ARC。有什么办法可以确保我的显示链接在我的视图之前被破坏?

编辑:我没有注意到崩溃实际上是由我拥有的断言触发的。我在每次调用 OpenGL 后都会断言,glGetError以确保我可以及早发现错误。致电glClearor后,[[view openGLContext] flushBuffer];我收到错误 1286,即GL_INVALID_FRAMEBUFFER_OPERATION.

这是合乎逻辑的,因为我的窗口和视图正在被释放,但这无助于解决问题。我不想忽略这些错误,因为它们显然可能在更多情况下发生,而不仅仅是这个。我仍然需要找到“正确”的方式来确保我的显示链接在我的视图之前被关闭。

4

1 回答 1

3

当应用程序终止时,其自动释放池中的任何内容都不会被释放——应用程序只是简单地exit让操作系统清理内存。由于没有任何内容被释放,因此没有任何内容会收到dealloc消息。

这意味着两件事:

  • 您不应将文件、连接或任何其他不仅仅驻留在内存中的东西的生命周期与对象的生命周期联系起来。
  • 您应该确保结束这些事物的生命周期以响应终止和释放。

有两种处理终止的方法。我通常在单窗口应用程序中执行此操作的方式是让我的应用程序的委托不是别的,并直接拥有我的主窗口控制器。另一种方法是将自己添加为NSApplicationWillTerminate通知的观察者并通过例如停止显示链接来响应通知。

如果清理的任何部分可能需要一些时间,您的应用程序的委托应该applicationShouldTerminate:通过返回来响应NSTerminateLater,并且您应该replyToApplicationShouldTerminate:在完成您需要做的任何事情后向应用程序发送一条消息。

原始问题的另一个解决方案——在你有机会关闭链接之前调用你的 CVDisplayLink 回调——完全相反:启用突然终止。启用后,您的应用程序将通过发送自身退出SIGKILL(通过命令行调用更清楚kill -9),这意味着您的每个线程都将立即停止。

当然,如果您确实有任何需要清理的东西(锁定文件、网络连接等),那么您应该在这些东西的生命周期内禁用突然终止,并准备在此期间定期终止。

于 2012-06-28T23:05:27.070 回答