3

私は Cocoa OpenGL アプリを作成し、このテクニカル ノートCVDisplayLinkに従ってメイン ループを実行しています。ループの実行には問題なく機能します。

問題は、終了すると、アプリケーションが既に終了した後、表示リンクのコールバックが独自のスレッドで呼び出されることがあるということです。これにより、レンダリング コードが呼び出され、OpenGL 関数 (この場合) を呼び出すとすぐにクラッシュしますglClear。これは、コンテキストが存在しなくなるためです。

私はCVDisplayLinkRelease(displayLink);NSViewのdealloc機能を持っていますが、呼び出されないようです.ARCが原因だと思います. ビューの前に表示リンクが確実に破棄されるようにする方法はありますか?

編集:クラッシュが実際に私が持っているアサートによってトリガーされていることに気づきませんでした。glGetErrorバグを早期に発見できるように、OpenGL を呼び出すたびにアサートします。glClearまたはを呼び出した後、[[view openGLContext] flushBuffer];エラー 1286 が表示されますGL_INVALID_FRAMEBUFFER_OPERATION

私のウィンドウとビューの割り当てが解除されているため、これは論理的に理にかなっていますが、問題は解決しません。これらのエラーは、明らかにこれ以外にも発生する可能性があるため、単に無視したくありません。ビューの前に表示リンクが確実にシャットダウンされるようにする「正しい」方法を見つける必要があります。

4

1 に答える 1

3

アプリケーションが終了すると、自動解放プール内の何も解放されません。アプリケーションは単にexits を実行し、オペレーティング システムがメモリをクリーンアップできるようにします。何も解放されないため、deallocメッセージは何も受信されません。

これは、次の 2 つのことを意味します。

  • ファイル、接続、またはメモリ内にのみ存在しないその他のものの有効期間を、オブジェクトの有効期間に関連付けるべきではありません。
  • 終了と割り当て解除に応じて、それらのライフタイムを確実に終了する必要があります。

終了を処理するには 2 つの方法があります。シングル ウィンドウ アプリで通常行う方法は、アプリケーションのデリゲートを他に何もなく、プライマリ ウィンドウ コントローラーを直接所有することです。NSApplicationWillTerminateもう 1 つの方法は、自分自身を通知のオブザーバーとして追加し、表示リンクを停止するなどして応答することです。

クリーンアップの一部に時間がかかる可能性がある場合、アプリケーションのデリゲートは をapplicationShouldTerminate:返すことで応答する必要があり、必要な処理が完了したらNSTerminateLaterアプリケーションにreplyToApplicationShouldTerminate:メッセージを送信する必要があります。

元の問題 (リンクを閉じる機会が得られる前に CVDisplayLink コールバックが呼び出される) に対するもう 1 つの解決策は、完全に反対です:突然の終了を有効にします。これが有効になっている場合、アプリケーションはそれ自体を送信して終了しますSIGKILL(コマンドライン呼び出しでよく知られていますkill -9)。これは、すべてのスレッドすぐに停止することを意味します。

もちろん、本当にクリーンアップする必要があるもの (ロック ファイル、ネットワーク接続など) がある場合は、それらの有効期間中の突然の終了を無効にし、その間の定期的な終了に備える必要があります。

于 2012-06-28T23:05:27.070 に答える