C言語による例外メカニズムの実装

プログラマーC ++、Java、C#...「純粋な」Cでコードを記述するとき、例外メカニズムがないという問題にしばしば直面します。 Cでエラーを処理する古典的な方法は、戻りコードをチェックすることです。 ネストが深い複雑なアルゴリズムでは、これは非常に不便です。 以下の方法は新しいものではありませんが、残念ながら多くの人は慣れていません。



そのため、POSIXにはいくつかの便利な関数があります: setjmplongjmp



 #include <setjmp.h>

 int setjmp(jmp_buf env);
 void longjmp(jmp_buf evn、int val);




例を考えてみましょう:



 #include <setjmp.h>
 jmp_buf jbuf;

 / * ...... * /

 / *ハンドラーを配置します* /
 int result = setjmp(jbuf);
スイッチ(結果){
   ケース0:/ *これはtryブロックです* /
   ケース1:/ * catchブロックの1つ* /
   ケース2:/ *別の問題* /
 };

 / * .... * /

 / *ここで例外をスローしたい* /
 longjmp(jbuf、EXCODEコード);




setjmp呼び出しは、スタックの状態を変数に保存します。 保存すると、setjmpは0を返します。この変数は、遷移をトリガーするコードで使用可能にする必要があります。 longjmpの出力後、すべてがsetjmpが0以外の値を返したように見えます。



注目に値するもの:

1)longjmpは制御を返しません。 setjmpへのロールバックがあるか、jmp_bufが壊れている場合-セグメンテーションエラー。

2)2番目のパラメーターlongjmpは、スタックが復元されたときにsetjmpが返す値です。 0は送信できません(この場合、1が返されます)。

3)上記のメカニズムは、Cのプログラムの「通常のロジック」を壊します。さらに、場合によっては、プログラムをより読みやすくすることができます。 これはgotoのように扱う必要があります。



mralephからのコメントの更新:

厳密に言えば、setjmpは「スタック状態」を保存しません。 レジスタ値のみを保存するため、作成された関数が終了した場合は特にjmp_bufは使用できません...



All Articles