エラー処理と例外処理
プログラムを書いていて、ロジックだけでは済まないのがエラーです。単にエラーと言っても構文エラーなどの実行する前にわかるものから、メモリ不足であるとかデバイスの都合や不具合など、その時になってみないとエラーになるかどうかわからないエラーもあります。
このようにその場にならないとわからないエラーを一般的には「実行時エラー(Runtime Error)」と呼んでいて、多くの場合これが発生するとその時点で実行していたプログラムはエラーメッセージを出力して停止してしまいます。エラーには原因があって、それを解消しなければ実行を続けることが出来ないのは当然ではあるのですが、いわゆるアプリケーションとしては理由が何であれ突然停止してしまうのはなかなか困るものです。
古のプログラミング言語であるFORTRANにも、かなり初期の頃から入出力に関してはエラーに対処するための構文が用意されていました。例えばファイルを開くOPEN文やREAD,WRITE文にはerr指定子が用意されていて()の中に”err=100”などと書いておくと、そこでエラーが発生した場合には指定された行番号に制御を移すことが出来ます。似たような機能にend指定子もあり、こちらは読み込み時にファイルの終端に達すると指定子に書いた行番号に飛びます。
15 ファイル操作 - Fortran入門
他の言語ではこのような処理を書けることは少なくC言語などでも原則としてエラーを示す「戻り値」が定義されていて、関数を呼び出すたびに戻り値をチェックしてエラーが発生した場合の処理を書くのが一般的です。
次にエラー処理が登場したのはおそらくBASICだと思います。初期のBASICとして有名なAltair BASICにはまだ無かったようですし、TinyBASICに近いAPPLE][の整数BASICにもエラー処理はありません。マイクロソフトは次々とBASICを改良してCP/M向けにMBASICを用意したのですが、初期のものにはやはりエラー処理はなかったようです。
Altair BASIC
MBASIC
ところがAPPLE][向けのAPPLESOFT BASICにはON ERROR文が登場します。元になった初期のCommodore BASICにはまだON ERRORは無く(こちらにON ERRORが登場したのはCBMになってから)、このあたりでMBASICと共に追加されたようです。
Commodore BASIC
Applesoft BASIC
Applesoft BASIC
ON ERROR GOTO に続いて行番号を指定し、この文を実行してから何らかのエラーが発生すると実行時エラーでプログラムは停止せずに、指定された行番号へ制御を移します。そこで何らかの処理を行い、最後にRESUME文を実行することで「エラーが発生した文」に制御を戻します。エラー処理を書くためにはエラーコードを知りたくなるのですが、そのための関数はなくPEEK(222)で読み出すのはAPPLEらしいです。
ON ERROR文は、その後のマイクロソフト系BASICでは標準的な機能となり、エラー番号を返すERRやエラーが発生した行を返すERL、そしてエラーを発生させるERROR文なども追加され、エラー処理から戻るときにも単なるRESUME以外に、行番号を指定して任意の場所に戻ったり、エラーの発生した「次の」行に戻るRESUME NEXTなども用意されました。
何せフロッピーディスクの時代ですから、ディスクが挿入されていなければすべてエラーです。プログラムを書いている時には不要にデータを書き込んでしまわないために、ディスクを引き出して使っていることも多いので、うっかりそのままプログラムを実行してエラーになるのは日常茶飯事です。こんな時にいちいちプログラムが停止してしまっては、途中のデータが消えてしまい困ることが頻発します。
この後に登場したUCSD-Pascalでは、このような場合に対処するにはコメント内にコンパイラに対するオプションを設定することでシステムがエラー処理を「行わない」ことで対処していました。まあデータを読んでみて意味のあるデータが無ければきっとエラーだったんだなと判断するわけです。指定は(*$I- *)みたいに書いていました(読み出したらすぐに戻さないとずっとエラーが出なくなってしまう)。
UCSD PASCAL II.0 Manual - P78あたりにオプション設定があります
http://pascal.hansotten.com/uploads/ucsd/ucsd/UCSD_PASCAL_II.0_Manual_Mar79.pdf
まあ使えなくはないのですが、エラー処理が書けるわけでもなく使いにくかったです。
さて、Adaが登場すると、そこには「例外」という仕組みが導入されていました。エラーと例外の何が違うのかについては微妙なものがあるのですが、それまでエラー処理として書いていた処理を例外という仕組みで扱うようになりました。
例外処理
例外とエラーの違い
その後のモダンなプログラミング言語では大体において何らかの例外機構を持つようになりました。もちろんBASICから進化したVBも同様です。VBに進化しても、ON ERRORは残ったのですが、コードがコンパイルされるようになると、互換性を維持するためにかなり無理なコードを生成するようになり大変に使いにくいものになってしまいました。ON ERRORの飛び先からRESUMEまたはRESUME NEXTで戻っていると、いつエラーが発生するかわからないので、文を実行するたびにERLを設定して戻る場所も覚えておくコードが必要になってしまったのです。実行速度はともかくコードサイズがなかなか大変なことになってしまうのですよね。そこで古いコードをそのまま使うときは諦めるにしてもVBにも導入された例外を使った新しい書き方に直す必要に迫られたわけです。
しかし、この例外処理は使いこなすにはなかなか難しいものがあります。エラーというのは立て続けに起こることも普通で、エラー処理の中でエラーが発生したらどうなるのかという問題は、CPUのマシン語レベルでも難しい問題ですし、自由にエラーを起こすことも難しいのでデバッグも大変です。すべての例外を処理することは結局不可能で、最終的には「予期しないエラー」という形でゴメンナサイということになるのは致し方ないのかもしれません。
それでも少なくとも予期できるようなエラーに関しては対処を書いておくのは今や必須で、標準ライブラリもエラーでなく例外を発生させるものも多いので、例外とはお付き合いしなければなりません。
ということで、C#やJavaなどでも必須な例外の知識なんですが、C++の場合にはどうするのかなんていうことをまとめてみようと思っています。
ヘッダ画像は、生成AIで作成しました。
#プログラミング言語 #エラー処理 #例外処理 #ONERROR #RESUME #FORTRAN #BASIC #PASCAL
いいなと思ったら応援しよう!
頂いたチップは記事を書くための資料を揃えるために使わせていただきます!