C プログラムのどこからでも呼び出された場合、C プログラミングにおける return ステートメントと exit ステートメントの違いは何ですか?
ベストアンサー1
- 戻る
for
現在の関数から戻ります。これはまたは のような言語キーワードですbreak
。 - 出口()どこから呼び出しても、プログラム全体を終了します。(stdio バッファなどをフラッシュした後)。
両方が (ほぼ) 同じことを実行する唯一のケースは、main()
関数内であり、main からの return が を実行しますexit()
。
ほとんどの C 実装では、main
は、 のようなことを実行するスタートアップ コードによって呼び出される実際の関数ですint ret = main(argc, argv); exit(ret);
。C 標準では、main
が返された場合にこれと同等のことが発生することが保証されていますが、実装によってそれがどのように処理されるかは異なります。
例return
:
#include <stdio.h>
void f(){
printf("Executing f\n");
return;
}
int main(){
f();
printf("Back from f\n");
}
このプログラムを実行すると、次のように出力されます:
Executing f Back from f
もう一つの例exit()
:
#include <stdio.h>
#include <stdlib.h>
void f(){
printf("Executing f\n");
exit(0);
}
int main(){
f();
printf("Back from f\n");
}
このプログラムを実行すると、次のように出力されます:
Executing f
「Back from f」は取得されません。また、#include <stdlib.h>
ライブラリ関数を呼び出す必要があることにも注意してくださいexit()
。
また、 のパラメータはexit()
整数であることにも注意してください (これは、ランチャー プロセスが取得できるプロセスの戻りステータスです。通常の使用法では、成功の場合は 0、エラーの場合はその他の値です)。
return ステートメントのパラメーターは、関数の戻り値の型になります。関数が void を返す場合は、関数の末尾の return を省略できます。
最後に、と のexit()
2 つの形式があります。これらの形式の違いは、(および main からの return) は、実際にプロセスを終了する前にまたは を使用して登録された関数を呼び出すのに対し、 (from 、またはその同義語である _Exit from ) はプロセスを直ちに終了することです。_exit()
exit()
exit()
atexit()
on_exit()
_exit()
#include <unistd.h>
#include <stdlib.h>
現在、C++ に固有の問題もあります。
C++ は、関数から抜ける ( -ing) ときに、C よりもはるかに多くの作業を実行しますreturn
。具体的には、スコープ外になるローカル オブジェクトのデストラクタを呼び出します。ほとんどの場合、プログラマはプロセスが停止した後のプログラムの状態をあまり気にしないので、大きな違いはありません。割り当てられたメモリは解放され、ファイル リソースは閉じられます。ただし、デストラクタが IO を実行するかどうかは問題になる場合があります。たとえば、OStream
ローカルで作成された自動 C++ は、終了の呼び出し時にフラッシュされず、フラッシュされていないデータの一部が失われる可能性があります (一方、静的データはOStream
フラッシュされます)。
古き良き CFILE*
ストリームを使用している場合、これは発生しません。これらは でフラッシュされますexit()
。実際、ルールは登録された終了関数の場合と同じで、 はFILE*
すべての正常終了時にフラッシュされます。これには が含まれますが、または abort()exit()
の呼び出しは含まれません。_exit()
C++では関数から抜け出す3つ目の方法、例外をスローする方法も用意されているので、覚えておく必要があります。この関数から抜け出す方法は意思デストラクタを呼び出します。呼び出しチェーンのどこにもキャッチされない場合、例外は main() 関数まで進み、プロセスを終了する可能性があります。
静的 C++ オブジェクト (グローバル) のデストラクタは、プログラム内return
から、main()
またはのいずれかを呼び出すと呼び出されます。プログラムがまたはを使用して終了された場合は呼び出されません。は、プログラムを直ちに停止してスタック トレースを取得する (事後分析用) 目的で、デバッグ モードで主に便利です。これは通常、デバッグ モードでのみアクティブになるマクロの背後に隠されています。exit()
_exit()
abort()
abort()
assert()
exit() はいつ役に立つのでしょうか?
exit()
現在のプロセスを直ちに停止することを意味します。何らかの回復不可能な問題が発生し、コードがそれ以上役に立たなくなった場合、エラー管理に役立ちます。制御フローが複雑で、エラー コードを上位にまで伝播する必要がある場合に便利です。ただし、これは不適切なコーディング プラクティスであることに注意してください。ほとんどの場合、プロセスを黙って終了することは最悪の動作であり、実際のエラー管理 (または C++ で例外を使用) が推奨されます。
ライブラリ内での直接呼び出しはexit()
特に良くありません。ライブラリの利用者に損害を与えることになるからです。何らかのエラー回復を実装するかどうかはライブラリの利用者の選択に委ねるべきです。exit()
ライブラリからの呼び出しがなぜ良くないのか例を挙げると、例えば次のような質問が出てきます。この質問。
fork() をサポートしているオペレーティング システムでは、fork() によって開始された子プロセスを終了する方法として、が正当に使用されていることは間違いありませんexit()
。fork() の前のコードに戻ることは通常、良い考えではありません。これが、exec() ファミリーの関数が呼び出し元に戻らない理由です。