std::exit
From cppreference.com
| ヘッダ <cstdlib> で定義 |
||
void exit( int exit_code ); |
(C++11まで) | |
| [[noreturn]] void exit( int exit_code ); |
(C++11以降) | |
通常のプログラム終了を引き起こします。
いくつかのクリーンアップ手順が実行されます
|
1) 静的記憶域期間を持つオブジェクトが破棄され、std::atexit の呼び出しによって登録された関数が呼び出されます
a) 静的記憶域期間を持つ非ローカルオブジェクトは、そのコンストラクタの完了とは逆の順序で破棄されます。
b) std::atexit で登録された関数は、登録されたときに既に呼び出されていた以前に登録された関数の後で呼び出される場合を除き、登録とは逆の順序で呼び出されます。
c) std::atexit で登録された各関数 f と、静的記憶域期間を持つ各非ローカルオブジェクト obj について、
d) 静的記憶域期間を持つ各ローカルオブジェクト obj について、obj は、obj のコンストラクタの完了時に std::atexit で obj のデストラクタを呼び出す関数が登録されたかのように破棄されます。 |
(C++11まで) |
|
1) 現在のスレッドに関連付けられたスレッドローカルな記憶域期間を持つオブジェクトのデストラクタ、静的記憶域期間を持つオブジェクトのデストラクタ、およびstd::atexitで登録された関数は、以下の保証を維持しながら並行して実行されます。
a) スレッドローカルオブジェクトの最後のデストラクタは、静的オブジェクトの最初のデストラクタの前に順序付けられます。
b) スレッドローカルまたは静的オブジェクトAのコンストラクタの完了または動的初期化がスレッドローカルまたは静的オブジェクトBの前に順序付けられていた場合、Bの破棄の完了はAの破棄の開始の前に順序付けられます。
c) 静的オブジェクトAの初期化の完了が、関数Fに対するstd::atexitの呼び出しの前に順序付けられていた場合、終了時のFの呼び出しはAの破棄の開始の前に順序付けられます。
d) 関数Fに対するstd::atexitの呼び出しが、静的オブジェクトAの初期化の完了の前に順序付けられていた場合、Aの破棄の開始は終了時のFの呼び出しの前に順序付けられます。
|
(C++11以降) |
- 上記において、
atexitで登録された関数、または静的/スレッドローカルオブジェクトのデストラクタが例外をスローした場合、std::terminateが呼び出されます。- コンパイラがオブジェクトの動的初期化を非ローカル初期化の静的初期化フェーズに持ち上げることを選択した場合、破棄の順序は本来の動的初期化を尊重します。
- 関数ローカル(ブロックスコープ)静的オブジェクトが破棄され、その後、別の静的オブジェクトのデストラクタからその関数が呼び出され、制御フローがそのオブジェクトの定義を通過する場合(またはポインタや参照を介して間接的に使用される場合)、動作は未定義です。
- 関数ローカル(ブロックスコープ)静的オブジェクトがクラスまたは配列のサブオブジェクトの構築中に初期化された場合、そのクラスのすべてのサブオブジェクトまたはその配列のすべての要素が破棄された後にのみ破棄されます。
2) すべてのCストリームはフラッシュされ、閉じられます。
3) std::tmpfile で作成されたファイルは削除されます。
4) ホスト環境に制御が戻されます。
exit_code が 0 または EXIT_SUCCESS の場合、成功した終了を示す実装定義のステータスが返されます。exit_code が EXIT_FAILURE の場合、失敗した終了を示す実装定義のステータスが返されます。その他の場合、実装定義のステータス値が返されます。スタックは巻き戻されません:自動記憶域期間を持つ変数のデストラクタは呼び出されません。
目次 |
[編集] main関数との関係
main関数から、return文によって、または関数の終わりに到達することによって戻ると、通常の関数終了が実行され(自動記憶域期間を持つ変数のデストラクタが呼び出されます)、その後std::exitが実行され、return文の引数(または暗黙的なreturnが使用された場合は0)がexit_codeとして渡されます。
[編集] パラメーター
| exit_code | - | プログラムの終了ステータス |
[編集] 戻り値
(なし)
[編集] 例
このコードを実行
#include <cstdlib> #include <iostream> struct Static { ~Static() { std::cout << "Static destructor\n"; } }; struct Local { ~Local() { std::cout << "Local destructor\n"; } }; Static static_variable; // Destructor of this object *will* be called void atexit_handler() { std::cout << "atexit handler\n"; } int main() { Local local_variable; // Destructor of this object will *not* be called const int result = std::atexit(atexit_handler); // Handler will be called if (result != 0) { std::cerr << "atexit registration failed\n"; return EXIT_FAILURE; } std::cout << "test\n"; std::exit(EXIT_FAILURE); std::cout << "this line will *not* be executed\n"; }
出力
test atexit handler Static destructor
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3 | C++98 | クリーンアップ中に、(1)関数が std::atexit に登録されている場合、または (2)静的ローカルオブジェクトが初期化される場合、動作が不明確でした。 |
明確化された |
[編集] 関連項目
| (クリーンアップせずに)異常なプログラム終了を引き起こす (関数) | |
| std::exit() 呼び出し時に呼び出される関数を登録します。 (関数) | |
| (C++11) |
完全なクリーンアップを行わずに、高速なプログラム終了を引き起こす (関数) |
| (C++11) |
std::quick_exit の呼び出し時に呼ばれる関数を登録する (関数) |
| C documentation の exit
| |