exit()
またはreturn
ステートメントのみを使用する必要がありmain()
ますか? 個人的にはreturn
、他の関数を読んでいるように感じ、コードを読んでいるときのフロー制御がスムーズであるため、ステートメントを好みます (私の意見では)。main()
また、関数をreturn
リファクタリングしたい場合でも、 exit()
.
何もしないexit()
特別なことはありますか?return
exit()
またはreturn
ステートメントのみを使用する必要がありmain()
ますか? 個人的にはreturn
、他の関数を読んでいるように感じ、コードを読んでいるときのフロー制御がスムーズであるため、ステートメントを好みます (私の意見では)。main()
また、関数をreturn
リファクタリングしたい場合でも、 exit()
.
何もしないexit()
特別なことはありますか?return
実際、違いはあり ますが微妙です。C++ にはより多くの影響がありますが、違いは重要です。
を呼び出すreturn
とmain()
、ローカル スコープのオブジェクトに対してデストラクタが呼び出されます。を呼び出すとexit()
、ローカル スコープのオブジェクトに対してデストラクタは呼び出されません。それを読み直してください。exit()
戻りません。つまり、一度呼んだら「裏切りなし」ということです。その関数で作成したオブジェクトは破棄されません。多くの場合、これは何の影響もありませんが、ファイルを閉じるなどの場合もあります (すべてのデータをディスクにフラッシュしたいですか?)。
static
を呼び出しても、オブジェクトはクリーンアップされることに注意してくださいexit()
。abort()
最後に、 を使用すると、オブジェクトが破棄されないことに注意してください。つまり、グローバル オブジェクト、静的オブジェクト、ローカル オブジェクトのデストラクタは呼び出されません。
リターンよりもエグジットを優先する場合は、注意して進めてください。
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
もう1つの違い
exit
は、標準ライブラリ関数であるため、ヘッダーを含めて標準ライブラリにリンクする必要があります。(C ++で)説明すると、これは有効なプログラムです。
int main() { return 0; }
ただし、使用exit
するには、次のものが必要です。
#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }
exit
さらに、これにより、からの呼び出しにmain
はゼロを返すのと同じ副作用があるという追加の仮定が追加されます。他の人が指摘しているように、これは作成している実行可能ファイルの種類(つまり、誰が呼び出しているか)によって異なりますmain
。Cランタイムを使用するアプリをコーディングしていますか?Mayaプラグイン?Windowsサービス?ドライバー?exit
いずれの場合も、がと同等であるかどうかを確認するための調査が必要になりreturn
ます。IMHOが本当に意味するexit
ときに使用すると、コードがさらに混乱します。OTOH、もしあなたが本当に意味があるのなら、ぜひそれを使ってください。 return
exit
優先する理由が少なくとも 1 つexit
あります。atexit
ハンドラーのいずれかが の自動ストレージ期間データを参照するmain
場合、または で標準ストリームの 1 つに自動ストレージ期間バッファを使用setvbuf
またはsetbuf
割り当てた場合main
、 から返されるとmain
生成されます未定義の動作ですが、呼び出しexit
は有効です。
別の潜在的な使用法 (通常はおもちゃのプログラム用に予約されています) は、 の再帰呼び出しでプログラムを終了することですmain
。
return
の標準プロトタイプでmain()
はint
.
とはいえ、標準の一部のバージョンでは特別な扱いがあり、明示的なステートメントmain
がない場合は 0 を返すと想定されています。return
次のコードがあるとします。
int foo() {}
int main(int argc, char *argv[]) {}
G++ は警告のみを生成foo()
し、 からの欠落した戻り値を無視しmain
ます:
% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function
プログラムが実際に終了する前に自動ストレージが再利用されるのを避けるために、exit() の使用に関する R のコメントを強く支持します。main()
のreturn X;
ステートメントはmain()
、 の呼び出しと正確に同等ではありませんexit(X);
。これは、 の動的ストレージが戻るとmain()
消えるためですが、代わりにmain()
の呼び出しが行われた場合は消えませんexit()
。
さらに、C やその他の C に似た言語return
では、呼び出し元の関数で実行が継続されることを読者に強く示唆するステートメントがあります。この実行の継続は通常、関数を呼び出した C スタートアップ ルーチンを数えれば技術的には正しいのですが、そうmain()
ではありません。プロセスを終了することを意味するとき、まさにあなたが意味すること。
結局のところ、他の関数内からプログラムを終了したい場合は、 を呼び出すmain()
必要がありexit()
ます。一貫してこれをmain()
行うと、コードがはるかに読みやすくなり、誰でもコードをリファクタリングしやすくなります。main()
つまり、他の関数からコピーされたコードは、呼び出しであるはずreturn
の偶発的なステートメントのために誤動作することはありません。exit()
したがって、これらすべての点を組み合わせると、少なくとも C では、ステートメントを使用してプログラムを終了するのは悪い習慣であるという結論になります。return
main()
exit() は、「return」がしない特別なことをしますか?
一般的ではないプラットフォーム用の一部のコンパイラでは、exit()
がその引数をプログラムの終了値に変換する場合がありますが、 からの戻り値main()
は変換せずに直接ホスト環境に値を渡すだけです。
標準では、これらの場合に同一の動作が要求されます (具体的には、int
互換性のあるものを返すことは、その値main()
で呼び出すことと同等である必要があるexit()
と述べています)。問題は、OS が異なれば、終了値を解釈するための規則が異なることです。多くの (多くの!) システムでは、0 は成功を意味し、それ以外はすべて失敗を意味します。しかし、たとえば VMS では、奇数の値は成功を意味し、偶数の値は失敗を意味します。から 0 を返すmain()
と、VMS ユーザーにはアクセス違反に関する厄介なメッセージが表示されます。実際にはアクセス違反はありませんでした。これは単にエラー コード 0 に関連付けられた標準的なメッセージでした。
その後、ANSI が登場し、祝福さEXIT_SUCCESS
れEXIT_FAILURE
、引数として に渡すことができましたexit()
。標準では、exit(0)
は と同じように動作する必要があるとも規定されてexit(EXIT_SUCCESS)
いるため、ほとんどの実装では が定義EXIT_SUCCESS
されて0
います。
したがって、標準では、たまたま値が 0 である失敗コードを返す標準的な方法が残っていないため、VMS で制約を受けることになります。
したがって、1990 年代初期の VAX/VMS C コンパイラは、 からの戻り値を解釈せずmain()
、ホスト環境に値を返すだけでした。しかし、それを使用exit()
すると、標準が要求することを実行できます。つまり、変換EXIT_SUCCESS
(または0
) を成功コードとEXIT_FAILURE
一般的な失敗コードに変換します。を使用するにはEXIT_SUCCESS
、に渡す必要があり、 から戻すことはできませんでした。そのコンパイラのより新しいバージョンがその動作を保持しているかどうかはわかりません。exit()
main()
移植可能な C プログラムは、次のように使用されます。
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, World!\n");
exit(EXIT_SUCCESS); /* to get good return value to OS */
/*NOTREACHED*/ /* to silence lint warning */
return 0; /* to silence compiler warning */
}
余談ですが、私の記憶が正しければ、VMS の終了値の規則は奇数/偶数よりも微妙です。実際には、下位 3 ビットのようなものを使用して重大度レベルをエンコードします。ただし、一般的に言えば、奇数の重大度レベルは成功またはその他の情報を示し、偶数の重大度レベルはエラーを示します。