C 言語で exit 関数を使用する
この記事では、C 言語で exit 関数を使用する方法の複数の方法を紹介します。
exit 関数を使って C 言語のプロセスを終了する
与えられたプログラムが UNIX ベースのオペレーティングシステム上で実行されているとき、それはプロセスと呼ばれます。そのプロセスは、長時間稼働するデーモン形式のプログラムであったり、単純なコマンドラインユーティリティであったりしますが、最終的にはどちらもいつかは終了点に到達します。終了は何かの障害やシグナルによって異常終了することもあれば、ライブラリ関数 exit を呼び出すことでプロセス自体が通常の動作として潔く終了することもある。この関数は親プロセスに返される終了値を指定する整数の引数を 1つ取ります。呼び出したプロセスでは exit 関数は戻らないことに注意してください。
exit 関数はシステムコール _exit (次の段落で説明する) の上に構築された標準的なライブラリ関数です。しかし、単に呼び出し元を終端点に導くだけではなく、より多くの操作を行います。つまり、_exit はプログラムのクリーンアップを行います。例えば、終了ハンドラとして登録されている関数を呼び出したり、標準の I/O ストリームバッファをフラッシュしたりしてから、_exit を呼び出します。なお、_exit は UNIX 固有のシステムコールであるのに対し、exit は標準 C ライブラリの一部であり、異なるプラットフォームでも利用できることに注意してください。
次の例では、EXIT_SUCCESS ステータスパラメータとして EXIT_SUCCESS を指定して exit 関数を呼び出す様子を示します。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
// Execute program code here
printf("Executing the program...\n");
sleep(5);
// exit(0);
exit(EXIT_SUCCESS);
}
出力:
Executing the program...
関数 atexit を用いて C 言語の終了ハンドラを登録する
これは単にユーザが実装した関数であり、exit コールを使ってプロセスが終了したときに呼び出されるべきものです。matexit は void (*function)(void) 型の関数ポインタを唯一の引数として受け取ります。
複数の関数は複数回の atexit 呼び出しで登録できるので、登録した関数を逆順に実行することになることに注意する必要があります。呼び出しに失敗した場合、atexit は 0 以外の値を返します。登録された関数は、外部からのシグナルによってプロセスが異常終了した場合には呼び出されない可能性があることに注意してください。次の例では、2つの static 関数を終了ハンドラとして登録し、5 秒間スリープした後に exit を呼び出してプロセスを終了させます。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void atexitFunc(void) { printf("atexitFunc called\n"); }
static void atexitFunc2(void) { printf("atexitFunc2 called\n"); }
int main(int argc, char *argv[]) {
if (atexit(atexitFunc) != 0) {
perror("atexit");
exit(EXIT_FAILURE);
}
if (atexit(atexitFunc2) != 0) {
perror("atexit");
exit(EXIT_FAILURE);
}
printf("Executing the program...\n");
sleep(5);
exit(EXIT_SUCCESS);
}
出力:
Executing the program...
atexitFunc2 called
atexitFunc called
最初に atexitFunc2 が呼び出され、その後に atexitFunc が呼び出されることに注意してください。あるいは、_exit システムコールを呼び出すことで直接プログラムを終了させることもできます。ただし、atexit で登録された関数は呼び出されないことに注意してください。一方、_exit は開いているファイルディスクリプタを閉じてしまうため、プロセスが終了するまでに未知の遅延が発生する可能性があります。さらに、return 文に任意のステータス値を指定することで、exit 関数が提供するのと同様の終了動作を行うことができます。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void atexitFunc(void) { printf("atexitFunc called\n"); }
static void atexitFunc2(void) { printf("atexitFunc2 called\n"); }
int main(int argc, char *argv[]) {
if (atexit(atexitFunc) != 0) {
perror("atexit");
exit(EXIT_FAILURE);
}
if (atexit(atexitFunc2) != 0) {
perror("atexit");
exit(EXIT_FAILURE);
}
printf("Executing the program...\n");
sleep(5);
_exit(EXIT_SUCCESS);
