Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume I/15-3
15-3 Try/Catch メカニズム
エラーマネージャは、Palm ハンドヘルドのマシン状態を意識しているため、その状態を正確に保存・復元することができます。コンパイラに組み込まれている Try/Catch はマシン独立のため、使用することはできません。
Try/Catch とは、基本的にはエラー発生時に使用する goto 文をすっきりと記述したものです。ルーチン内での典型的なエラー処理の方法は、エラー発生時にルーチン末尾にジャンプし、一般的なクリーンアップ処理を実行するというものです。ネストしたルーチン内でのエラーはもう少し複雑です。これは、各サブルーチンの復帰値をチェックして続行すべきかどうかを判定する必要があるからです。
try/catch を設定する場合、エラー発生時にジャンプする先をコンパイラに指示します。そのエラー処理コードには ErrThrow をコールすることでいつでもジャンプすることができます。コンパイラは ErrThrow コールを見つけると、エラー処理コードへの goto を実行します。しかし、ErrThrow コールの最大の利点は、ネストしたサブルーチン内のエラーを処理できることです。
ネストしたサブルーチンから ErrThrow がコールされた場合でも、実行はただちにより上位レベルのエラー処理コードに移動します。コンパイラとランタイム環境は処理のネストによってプッシュされたスタックフレームを自動的に巻き戻し、上位レベルにあるエラー処理セクションに移動します。各サブルーチンコールの後に復帰値をチェックする必要はなくなり、ソースコードが非常に簡潔に、そしてサイズも小さくなります。.
Try/Catch メカニズムの使用
以下に、エラーマネージャの Try/Catch メカニズムを使用した典型的な処理の例を示します。
リスト 15.1 Try/Catch メカニズムの例
ErrTry { p = MemPtrNew(1000); if (!p) ErrThrow(errNoMemory); MemSet(p, 1000, 0); CreateTable(p); PrintTable(p); } ErrCatch(err) { // Recover or clean up after a failure in the // above Try block."err" is an int // identifying the reason for the failure. // You may call ErrThrow() if you want to // jump out to the next Catch block. // The code in this Catch block doesn’t // execute if the above Try block completes // without a Throw. if (err == errNoMemory) ErrDisplay("Out of Memory"); else ErrDisplay("Some other error"); } ErrEndCatch // You must structure your code exactly as // above. You can’t have an ErrTry without an //ErrCatch { } ErrEndCatch, or vice versa.
ErrTry ブロック内部で ErrThrow がコールされると、コントロールパスはただちに ErrCatch ブロックに移動します。CreateTable サブルーチンの内部から ErrThrow がコールされた場合でも、制御はダイレクトに ErrCatch ブロックに渡されます。ErrThrow がコールされることなく ErrTry ブロックが終了した場合、ErrCatch ブロックは実行されません。
複数の ErrTry ブロックをネストさせることができます。例えば、CreateTable でエラーが発生した場合になんらかのクリーンアップ処理をしたい場合、
- CreateTable 関数内に ErrTry/ErrCatch ブロックを作成します。
- その ErrCatch ブロックでまずクリーンアップ処理を行ないます。
- 上位の ErrCatch にジャンプするために ErrThrow をコールします。