C++ 11では、プログラムの実行を終了する新しい方法_std::quick_exit
_が導入されています。
N3242 18.5(p。461)の引用:
_[[noreturn]] void quick_exit(int status) noexcept;
_効果:_
at_quick_exit
_の呼び出しによって登録された関数は、登録の逆の順序で呼び出されます。ただし、関数は、登録時にすでに呼び出されていた以前に登録された関数の後に呼び出されます。 _quick_exit
_を呼び出した結果としてオブジェクトが破棄されてはなりません。関数がスローされた例外のハンドラーを提供しないために、コントロールが_quick_exit
_によって呼び出される登録済み関数を離れる場合、terminate()
が呼び出されます。 [注:_at_quick_exit
_は、登録された関数を、それを登録したスレッドとは異なるスレッドから呼び出す可能性があるため、登録された関数は、スレッドの保存期間を持つオブジェクトのIDに依存しないでください。 — end note]登録された関数を呼び出した後、_quick_exit
_は_Exit(status)
を呼び出すものとします。 [注:標準のファイルバッファーはフラッシュされません。 ISO C7.20.4.4を参照してください。 —エンドノート]
std::abort(void)
とstd::_Exit(int status)
の定義は、ステータスを親プロセスに渡す機能のみが異なるため、私の疑問が生じます。
_std::quick_exit
_と_std::abort
_のセマンティクスの唯一の違いは、_std::quick_exit
_が_std::at_quick_exit
_を使用して登録された関数を呼び出し、返されるステータスを設定できることを意味しますか?
この機能を導入した理由は何でしたか?
良い記事があります ここで入手可能 、私はそれを要約します。この機能は、スレッドを使用するときにプログラムをクリーンに終了することの難しさに特に対処するために追加されました。本質的に、終了は高度に非同期のイベント、ユーザーがユーザーインターフェースを閉じる、管理者がマシンをシャットダウンするなどによって開始されます。これは、プログラムが開始したスレッドの状態に関係なく発生し、ほとんどの場合、非常に予測不可能な状態にあります。
理想的な世界では、プログラムのmain()関数は、通常はイベントを通知することにより、スレッドに終了を要求し、スレッドが終了するのを待ってから、exit()によるクリーンシャットダウンのためにmain()を終了します。ただし、その理想は非常に達成するのが困難です。たとえば、I/Oが完了するのを待つなど、スレッドがシステムコールの奥深くに埋め込まれる可能性があります。または、別のスレッドから正しい順序で通知される必要がある同期オブジェクトをブロックしています。結果が快適になることはめったになく、実際のプログラムは終了時にデッドロックすることがよくあります。または、シャットダウンの順序が予期しない場合にクラッシュします。
この問題には、単純で非常に魅力的な回避策があります。代わりに_exit()を呼び出します。 Kaboom、プログラムは終了し、オペレーティングシステムは榴散弾を箒します。しかし、明らかにクリーンアップがまったく行われず、ファイルの半分が書き込まれたり、dbaseトランザクションが不完全だったりするなどのアーティファクトが発生することがあります。
std :: quick_exit()は代替手段を提供します。 _exit()に似ていますが、at_quick_exitに登録されているものは何でも、コードを実行するオプションがあります。
std::abort
は、「at_exit/at_quick_exit」を使用して登録された関数を呼び出さずにアプリケーションを終了します。一方、std::quick_exit
は、ご指摘のとおり、std::at_quick_exit
を使用して登録された関数を呼び出します。
std::abort
通常abortsアプリケーション。これは、異常な状況が発生し、クリーンアップを行わずにアプリケーションを閉じる必要がある場合に呼び出す必要があります。 std::abort
ドキュメントから:
SIGABRTがシグナルに渡されたシグナルハンドラーによってキャッチされ、ハンドラーが戻らない場合を除いて、プログラムの異常終了を引き起こします。
クリーンアップを実行する場合は、std::quick_exit
がより適切になります。この最後の関数を使用すると、アプリケーションを正常に停止することもできます。これは、std::_Exit
のようなシグナル(SIGABRTにシグナルを送信し、アプリケーションを異常に停止させる)の代わりにstd::abort
を呼び出すことになるためです。
std::exit
を使用すると、自動スレッドローカル変数と静的変数をクリーンアップしながら、アプリケーションを正常に終了できます。 std::quick_exit
はしません。そのため、名前に「quick_」が含まれています。クリーンアップフェーズをスキップするため、高速です。
したがって、両方の機能の間に実際の意味上の違いがあります。 1つはアプリケーションを異常に停止し、もう1つはグレースフル終了を実行して、いくつかのクリーンアップを実行できるようにします。