C言語はsetjmp/longjmpを利用してC++を模倣する階層異常処理メカニズムを実現する

2602 ワード

従来のC言語異常処理メカニズム
従来のC言語異常処理では、一般に、呼び出し元に異なる戻り値を設定したり、エラーを表すグローバル変数値を設定したりすることで、実行が正常であるか、様々なエラー、異常、警告が発生していることを表す.一方,呼び出し者は,被呼び出し者の戻り値により異常が発生したか否かを判断し,異常を処理する.以下に、この処理の簡単な例を示します.
fun1()
{
....
int result=fun2();
switch(result)
{
case 1 ....
case 2 ....
....
}
....
}

fun2()
{
.... 
.... return -1;
....
.... return 1;
....
}

より合理的な異常処理メカニズム
従来のC言語異常処理メカニズムでは,階層別に異常を伝達する必要がある場合,各層は各下位インタフェースの戻り値を判断し,対応するエラー処理コードを記述する.このレイヤで処理できないエラーは、上位インタフェース処理にもアップロードされます.このような階層の呼び出しは、階層が多い場合、エラーが階層ごとに伝達され、大量のコードを記述する必要があり、プログラマーに大きな迷惑をかけず、エラーが発生しやすい.さらに、多くのエラー処理コードは、インタフェースの主要なプロセスの読み取り可能性を低下させる.絶えず検査とデバッグを経て、エラーが発生するのは小確率イベントであるが、各層が判断し、効率に影響を与える必要がある.
そのため、大規模なCプロジェクトでは、どのような異常処理メカニズムが必要なのかを反省する必要があります.例えばJAVAでは、C++のtry/catch/throw異常処理メカニズムがより効果的であり、エラーが発生した後、レイヤごとに異常を伝達することなく、エラーを処理する能力のある上位インタフェースにすぐにジャンプすることができる.
具体的な実装の詳細
C言語ではsetjmp/longjmpによりC++異常処理と同様のメカニズムを実現できる.
彼らの原型はint setjmp(jmp_buf env);               void longjmp(jmp_buf env, int val);
setjmp/longjmpを使用するには、プログラムにsetjmpを追加する必要があります.hこのヘッダファイル.setjmp()の役割は、バッファenvbufにシステムスタック内のコンテンツを保存することであり、マクロの戻り値は0である.longjmp()は、プログラムを最近の呼び出しsetjmp()にジャンプさせ、次の文を再実行します.しかしlongjmp()の2番目のパラメータは、longjmp()を呼び出した後にsetjmp()の戻り値を再び実行する値をsetjmp()に渡し、異なる戻り値を利用して最初のsetjmp()と区別します.
説明する必要があるのはsetjmp/longjmpが関数にまたがることができるため、関数呼び出し階層にまたがる異常処理メカニズムを実現するために利用することができる.
簡単な使用例を次に示します.
私たちは3つの小さなファイルをmainとしています.c file1.c file2.c、以下に彼らをリストします.
int main()
{
	jmp_buf main_stat;
	if(setjmp(error_stat)!=0)
		{
			printf(" error in main 
"); return -1; } file1(); return 0; }
int file1()
{
	jmp_buf file1_stat;
	memcpy(&file1_stat,&error_stat,sizeof(file1_stat));
	if(setjmp(error_stat)!=0)
		{
			printf(" error in file1 
"); memcpy(&error_stat,&file1_stat,sizeof(file1_stat)); longjmp(error_stat,1); } file2(); }
int file2()
{
	jmp_buf file2_stat;
	memcpy(&file2_stat,&error_stat,sizeof(file2_stat));
	if(setjmp(error_stat)!=0)
		{
			printf(" error in file2 
"); memcpy(&error_stat,&file2_stat,sizeof(file2_stat)); longjmp(error_stat,1); } printf(" start error
"); longjmp(error_stat,1); }

コンパイル、実行、出力結果:
 start error   error in file2   error in file1   error in main 
これは単純な例にすぎず,階層に従って伝達され,階層に従って伝達されないコードはこれと類似している.
小結
setjmp/longjmpを用いることで,C言語においてC++階層伝達を模倣した異常処理機構を実現できる.この実現方式は効率が高く,大規模な工事プロジェクトで異常処理をうまく実現でき,プログラムの複雑さを軽減できる.