(1) | 終了処理の登録と実行(atexit)ルーチンの作成例 |
終了処理の登録を行うライブラリatexit関数の作成法を示します。
atexit関数では、引数として渡された関数のアドレスを、終了処理のテーブルに登録します。登録された関数の個数が限界値(ここでは、登録できる個数を32個とします)を超えた場合、あるいは同じ関数が二度以上登録された場合はリターン値として0以外(ここでは1)を返します。そうでなければ0を返します。
以下にプログラム例を示します。
#include <stdlib.h>
long _atexit_count=0 ;
void (*_atexit_buf[32])(void) ;
#ifdef __cplusplus
extern "C"
#endif
long atexit(void (*f)(void))
{
int i;
for(i=0; i<_atexit_count ; i++) // 既に登録されていないかチェックします
if(_atexit_buf[i]==f)
return 1;
if (_atexit_count==32) // 登録数の限界値をチェックします
return 1;
else {
_atexit_buf[_atexit_count++]=f; // 関数のアドレスを登録します
return 0;
}
}
|
(2) | プログラムの終了(exit)ルーチンの作成例 |
プログラムの終了処理を行うライブラリexit関数の作成法を示します。プログラムの終了処理は、ユーザシステムによって異なりますので、以下のプログラム例を参考に、ユーザシステムの仕様に従った終了処理を作成してください。
exit関数は、引数として渡されたプログラムの終了コードに従ってプログラムの終了処理を行い、プログラム起動時の環境に戻ります。ここでは、終了コードを外部変数に設定して、main関数を呼び出す直前にsetjmp関数で退避した環境に戻ることによって実現します。プログラム実行前の環境に戻るためには、次の関数「callmain」を作成し、初期設定関数「PowerON_Reset_PC」から関数「main」を呼び出す代わりに、関数「callmain」を呼び出してください。
以下にプログラム例を示します。
#include <setjmp.h>
#include <stddef.h>
extern long _atexit_count ;
extern void (*_atexit_buf[32])(void) ;
#ifdef __cplusplus
extern "C"
#endif
void _CLOSEALL(void);
int main(void);
extern jmp_buf _init_env ;
int _exit_code ;
#ifdef __cplusplus
extern "C"
#endif
void exit(int code)
{
int i;
_exit_code=code ; // _exit_codeにリターンコードを設定します
for(i=_atexit_count-1; i>=0; i--) // atexit関数で登録した関数を順次実行します
(*_atexit_buf[i])();
_CLOSEALL(); // オープンした関数を全てクローズします
longjmp(_init_env, 1) ; // setjmpで退避した環境にリターンします
}
#ifdef __cplusplus
extern "C"
#endif
void callmain(void)
{
// setjmpを用いて現在の環境を退避し、main関数を呼び出します
if(!setjmp(_init_env))
_exit_code=main(); // exit関数からのリターン時には処理を終了します
}
|
異常終了の場合は、ご使用になっているユーザシステムの仕様に従って、プログラムを異常終了させる処理を行ってください。
C++プログラムを使用する場合、以下のときにもabort関数を呼び出します。
- | クラス配列のdelete時に情報が取れなかった場合 |
- | クラスオブジェクトのデストラクタコール情報登録時に矛盾が発生した場合 |
以下、標準出力装置にメッセージを出力したあと、ファイルをクローズしてから無限ループしてリセットを待つプログラム例を示します。
#include <stdio.h>
#ifdef __cplusplus
extern "C"
#endif
void _CLOSEALL(void);
#ifdef __cplusplus
extern "C"
#endif
void abort(void)
{
printf("program is abort !!\n"); // メッセージを出力します
_CLOSEALL(); // ファイルをクローズします
while(1) ; // 無限ループします
}
|