(Translated by https://www.hiragana.jp/)
例外処理 - Wikipedia コンテンツにスキップ

例外れいがい処理しょり

出典しゅってん: フリー百科ひゃっか事典じてん『ウィキペディア(Wikipedia)』

例外れいがい処理しょり(れいがいしょり、英語えいご: exception handling)とは、IT業界ぎょうかいもちいられる専門せんもん用語ようごで、ある抽象ちゅうしょうレベルにおけるシステムの設計せっけい想定そうていされておらず、ユーザー操作そうさによって解決かいけつできない問題もんだい対処たいしょするための処理しょりである。例外れいがい処理しょり結果けっかとして問題もんだい解決かいけつされないとシステム障害しょうがいになる。システム停止ていしデータ破損はそん原因げんいんになり、ユーザーに損害そんがいあたえる可能かのうせいがあるため、システム開発かいはつ例外れいがい処理しょり重要じゅうようされている[1][2][3]

システムの設計せっけい想定そうていされておらず、継続けいぞく不能ふのう継続けいぞくすると問題もんだいになるよう状態じょうたいとしては、つぎのようなものがげられる。

  • ハードウェア故障こしょう
  • オペレーティングシステムひとし、システムの設定せっていミス
  • ライブラリ欠損けっそん
  • ユーザー入力にゅうりょく間違まちが
    • 数値すうち入力にゅうりょく要求ようきゅうしている場合ばあいでの、英単語えいたんご入力にゅうりょく
    • 存在そんざいしないデータベースのテーブル/カラムやファイル指定してい
  • 必要ひつようシステムとの疎通そつうれない
  • ゆるされない演算えんざん0での除算じょざん実数じっすう演算えんざんかい虚数きょすうになる演算えんざんなど)
  • てられていない記憶きおく領域りょういきへのアクセス
  • プログラミング言語げんごにおいて、なに参照さんしょうしていないハンドルやポインター(Nullポインタ)を参照さんしょうして操作そうさしようとした場合ばあいれいとしてJavaにおけるNullPointerExceptionなど)。

注意ちゅういてんとして、あらゆる例外れいがい抽象ちゅうしょうレベルに依存いぞんせずすべて異常いじょうけいであるとはかぎらない。たとえばページフォルトはカーネル内部ないぶのメモリなど例外れいがいゆるされない環境かんきょうではエラーとなるが、仮想かそう記憶きおく採用さいようしたOSにおけるユーザプロセスのメモリは常時じょうじ物理ぶつりてき存在そんざいするとはかぎらないためページフォルトを正常せいじょうけいとして処理しょりする必要ひつようがある。また、例外れいがい処理しょりちゅうにさらなる例外れいがい発生はっせいした場合ばあいは、通常つうじょうなら正常せいじょうけいとなる事象じしょう異常いじょうけいわる場合ばあいがある。くわしくは#例外れいがいのネスト参照さんしょうされたい。

例外れいがい処理しょり動作どうさ重要じゅうようせい

[編集へんしゅう]

例外れいがい処理しょり動作どうさとしては、システムを構成こうせいするプログラムのかく階層かいそうで、さき想定そうていしていない入力にゅうりょくって問題もんだいきた場合ばあいに、問題もんだいわせた例外れいがい発生はっせいさせてもと処理しょりかえす。もと例外れいがいかえことによって、もと問題もんだい解決かいけつおこなわれることに期待きたいするが、どの階層かいそう例外れいがい処理しょりでも問題もんだい解決かいけつできない場合ばあいは、システムの内部ないぶ状態じょうたい矛盾むじゅんのこり、システム障害しょうがいとなる。例外れいがい発生はっせいのち、システムが動作どうさしていても、例外れいがいへの対処たいしょ結果けっか設計せっけいから逸脱いつだつしている場合ばあい、システムの内部ないぶ状態じょうたい矛盾むじゅんきたしており、ストレージデータベースネットワーク無意味むいみなデータを出力しゅつりょくする可能かのうせいしょうじ、データ破損はそんのみならず、連携れんけいするシステムにも矛盾むじゅん伝播でんぱして広範こうはんなシステム障害しょうがいつながる可能かのうせいがある。したがって、例外れいがい処理しょりはシステム障害しょうがい未然みぜんふせ意味いみ非常ひじょう重要じゅうようである。

例外れいがいとエラーのちが

[編集へんしゅう]

例外れいがい(exception)はシステム担当たんとうしゃ問題もんだい解決かいけつおこな必要ひつようがある。例外れいがい問題もんだい解決かいけつ手段しゅだんには例外れいがい無視むしすることもふくまれるが、明確めいかく根拠こんきょをもって無視むしする必要ひつようがある(設計せっけい一環いっかんとして一部いちぶ例外れいがい無視むししても問題もんだいないと判断はんだんする,連携れんけいするシステムのメンテナンスちゅう例外れいがい発生はっせい不可避ふかひ場合ばあいはメンテナンス完了かんりょうつ)。例外れいがいたいして、ユーザーが解決かいけつすべき問題もんだいエラー(error)とぶ(ただし、業務ぎょうむシステム開発かいはつではエラーを業務ぎょうむエラー、例外れいがいをシステムエラーと表現ひょうげんする場合ばあいもあり、技術ぎじゅつしゃあいだでの厳密げんみつ統一とういつ見解けんかい存在そんざいしない)[1][2][3]なんらかのシステム開発かいはつおこな会社かいしゃでは、例外れいがいへの対処たいしょ不適切ふてきせつであるとユーザーに損害そんがいあたえるため、システム障害しょうがい発生はっせいさせるような例外れいがい発生はっせい製品せいひん瑕疵かしとしてあつか必要ひつようがある。

例外れいがい安全あんぜんせい

[編集へんしゅう]

あるコードない実行じっこうちゅう失敗しっぱいが、メモリリーク格納かくのうデータの整合せいごう不正ふせい出力しゅつりょくなどの有害ゆうがい効果こうかしょうじないとき、そのコードへん例外れいがい安全あんぜんであるとう。例外れいがい安全あんぜんなコードは例外れいがい発生はっせいしたとしてもそのコードがそなえる不変ふへん条件じょうけんたさなければならない。例外れいがい安全あんぜんせいにはいくつかのレベルがある[4][5]:

  1. 送出そうしゅつ保証ほしょう、もしくは失敗しっぱい透過とうかせい: 操作そうさ成功せいこうするものと保証ほしょうされ、例外れいがいてき状況じょうきょうなかであってもすべての要求ようきゅうたす。もし例外れいがい発生はっせいしたとしても、その例外れいがいをより上位じょうい送出そうしゅつはしない。(最高さいこうレベルの例外れいがい安全あんぜんせい
  2. つよ例外れいがい安全あんぜんせいコミット・オア・ロールバックセマンティクス[6]あるいは変更へんこう保証ほしょう: 操作そうさ失敗しっぱいすることがあるが、失敗しっぱいした操作そうさ副作用ふくさようこさないことが保証ほしょうされ、すべてのデータはもと保持ほじする。
  3. 基本きほんてき例外れいがい安全あんぜんせい: 失敗しっぱいした操作そうさ不完全ふかんぜん実行じっこうによって副作用ふくさようこることがあるが、状態じょうたい不変ふへん条件じょうけんたもたれる。あらゆる格納かくのうデータは、もはや実行じっこうまえとはことなるとしても、有効ゆうこうつ。
  4. 例外れいがい安全あんぜんせいなし: なに保証ほしょうされない。(最低さいていレベルの例外れいがい安全あんぜんせい

言語げんごサポート

[編集へんしゅう]

いくつかのプログラミング言語げんごではみの例外れいがい処理しょり機能きのう用意よういしている。たとえばAdaC++JavaScalaC#JavaScriptOCamlがそうである。これらの言語げんごでは専用せんよう言語げんご機能きのうによってプログラマが例外れいがい処理しょり記述きじゅつする手間てま軽減けいげんしている。

例外れいがい発生はっせいしたことを見落みおとして正常せいじょう動作どうさ継続けいぞくしてしまうと、より深刻しんこく致命ちめいてき異常いじょうまねくおそれがある。それをけるには例外れいがい発生はっせいしたことのチェックを綿密めんみつおこない、例外れいがい検出けんしゅつされた場合ばあいには適切てきせつ事後じご処理しょりおこなない。しかし、だい規模きぼなプログラムではこのようなチェックは膨大ぼうだいなものとなり、本来ほんらい目的もくてきとしている正常せいじょう処理しょりよりもおおくの記述きじゅつ必要ひつようとする場合ばあいすらある。

そこで、これらの言語げんごでは例外れいがい発生はっせいチェックをほぼ自動じどうしている。例外れいがい発生はっせいすると現在げんざい処理しょり中断ちゅうだんする。発生はっせいした例外れいがい事後じご処理しょり担当たんとうできるハンドラをさがして次々つぎつぎコールスタック関数かんすうし)をさかのぼり、適切てきせつなハンドラをつけるとそれに事後じご処理しょりまかせる。これにより、さかのぼ途中とちゅうにあったこの例外れいがい処理しょりする能力のうりょくたない処理しょり自動的じどうてき中断ちゅうだんされることになる。

Schemeでは言語げんごレベルでの例外れいがい処理しょりたないが、これは継続けいぞく存在そんざいするため例外れいがいライブラリレベルで実現じつげんできるからである(標準ひょうじゅん仕様しようであるSRFI-34で定義ていぎされている)。

C++による例外れいがい処理しょり構文こうぶんれい

[編集へんしゅう]
void Function0(void) throw(...) // (2)
{
    // (1)
    throw 0;
    throw "message";
    throw std::runtime_error( "message" );
    throw;
}

void Function1(void)
{
    try
    {
        Function0();
    }
    catch( int exception ) // (3)
    {
        // 回復かいふく処理しょり
    }
    catch( char const *exception ) // (4)
    {
        // 回復かいふく処理しょり
    }
    catch( std::exception const &exception ) // (5)
    {
        // 回復かいふく処理しょり
    }
    catch(...) // (6)
    {
        // 回復かいふく処理しょり
        throw; // (7)
    }
}
void Function2(void)
try
{
    // (8)
}
catch (...)
{
}

tryブロックちゅうした関数かんすうFunction0()が(1)のthrow実行じっこうすると、Function1()catchぶんへと制御せいぎょうつる。C++では後発こうはつ言語げんごとはことなり、std::exceptionあるいはその派生はせいがた以外いがいかたでもthrowげることができ、(3)(4)(5)のようかた対応たいおうしたcatchぶん捕捉ほそくすることができる。なお、(1)では例示れいじのため複数ふくすうthrowいているが、実際じっさいには1個いっこthrow実行じっこうした時点じてんcatchぶん移動いどうする。

例外れいがい構文こうぶんには例外れいがい存在そんざいしないことを明示めいじするnoexcept標準ひょうじゅんされている。

C++の特徴とくちょうてき構文こうぶんとして、(6)の省略しょうりゃくもちいたcatchが存在そんざいする。あらゆる例外れいがい捕捉ほそく可能かのうであり、catchりこぼした例外れいがいでもつかまえる必要ひつようがある場合ばあいもちいる。指定していしないthrowつかまえられるのも省略しょうりゃくもちいたcatchだけである。また、Microsoft Visual C++といった一部いちぶ処理しょりけいでは、コンパイラオプションの指定していによりC++例外れいがいだけでなくOSがげた構造こうぞう例外れいがい省略しょうりゃくもちいたcatch捕捉ほそくできる[7]catchぶんなかでは(7)のように引数ひきすうthrowもちいた場合ばあい例外れいがい再送さいそう意味いみする。省略しょうりゃくもちいたcatch場合ばあい例外れいがい情報じょうほう判断はんだんできないため必須ひっすであるが、省略しょうりゃく使つかわないcatchでも派生はせいがた例外れいがい基底きていがたってしまった場合ばあいのスライシングをふせぐために必要ひつようとなる。

tryブロックは(8)のように関数かんすう全体ぜんたい適用てきようすることもできる。これをfunction-try-blockとう。catchぶんでは局所きょくしょ変数へんすう参照さんしょうできず引数ひきすうだけしか参照さんしょうできないが、コンストラクタ初期しょきリストで発生はっせいした例外れいがいデストラクタ[8]からげられた例外れいがいはこのかたでしか捕捉ほそくすることができない。

例外れいがい処理しょり構文こうぶん最初さいしょ実装じっそうしたのはAdaであるが、C++の例外れいがい処理しょり構文こうぶんはJavaやJavaScript、C#などおおくの後発こうはつ言語げんご規範きはんとなった。

例外れいがい指定してい

[編集へんしゅう]

C++の例外れいがい指定してい (Exception Specification、例外れいがい仕様しようとも) は、関数かんすうから伝達でんたつされる例外れいがい種類しゅるい明示めいじする言語げんご機能きのうである[9]たとえば void f() throw(int) はintがたのエラーをthrowしうることを明示めいじしている。例外れいがい指定していはコンパイラによる静的せいてき例外れいがい検査けんさ想定そうていして用意よういされた機能きのうだがかくコンパイラには実装じっそうされず、C++11で推奨すいしょうになり、C++17をもって廃止はいしされた[10]

Javaによる例外れいがい処理しょり構文こうぶんれい

[編集へんしゅう]
    public void throwError() throws Exception {
        throw new Exception();
    }

    public void catchException() {
        try {
            throwError();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Javaでは例外れいがいクラスとして実装じっそうする。例外れいがいを「げる(throw)」メソッドはthrows Exceptionのように指定していする。JavaプラットフォームうえJava言語げんご使用しようし、発生はっせいする例外れいがいjava.lang.Exception継承けいしょうしているが、しかしjava.lang.RuntimeExcption継承けいしょうしていない場合ばあいtry/catchぶん例外れいがい処理しょり明示めいじてき記述きじゅつするか、メソッドにthrows追加ついかする必要ひつようがある。ただし、Javaプラットフォームじょううご言語げんごでも、GroovyScalaなど、Java言語げんご以外いがいおおくは、RuntimeException以外いがい例外れいがいたいしてかならずしも明示めいじてき記述きじゅつしなくてもくなっている。初期しょきのJava(JDK1.0)では、I/O処理しょりなど手段しゅだんでは例外れいがい発生はっせい回避かいひすることができない種類しゅるい例外れいがいたいしてはRuntimeException継承けいしょうさせないという設計せっけい思想しそうになっていた。

Smalltalkによる例外れいがい処理しょり構文こうぶんれい

[編集へんしゅう]
| value |

value := "しきであるためもど存在そんざいする"
[
	Notification signal: '接続せつぞく準備じゅんび完了かんりょう'. 

	1. "本来ほんらいはvalueに代入だいにゅうされるが例外れいがい発生はっせいしているため代入だいにゅうしない"
]
	on: Error, Notification "複数ふくすう例外れいがい同時どうじ捕捉ほそくできる"
	do:
	[ :exception |
        exception return: 0. "1のわりにvalueに0を代入だいにゅうする。"
	]
	on: Exception
	do:
	[ :exception |
        exception pass. "処理しょりできない例外れいがい上位じょうい例外れいがい処理しょりゆだねる。"
	].

言語げんご機能きのうとしては例外れいがい処理しょり構文こうぶん存在そんざいしないが別途べっと例外れいがい処理しょりそなえる言語げんご存在そんざいする。Smalltalk言語げんご機能きのうとして制御せいぎょ構文こうぶんほとんどない。このため例外れいがい処理しょり構文こうぶんもブロックをわせたメッセージしきとして記述きじゅつするようになっている。言語げんご機能きのうではないためきわめて柔軟じゅうなんせいがありブロックのもど変更へんこうしたり例外れいがい発生はっせいしたしき途中とちゅうから復帰ふっきしたりなど様々さまざま制御せいぎょ可能かのうになっている。

制御せいぎょフローへの転用てんよう

[編集へんしゅう]

例外れいがい処理しょり過程かていでは処理しょりながれが通常つうじょう制御せいぎょとはおおきく変化へんかすることとなるが、これを(エラー処理しょり以外いがい目的もくてきで、正常せいじょうけいにおいて)積極せっきょくてき利用りようすることは、アンチパターンとされることもある。

一方いっぽうRuby[11]Python[12]では、イテレータ終端しゅうたんたっするという、無限むげんループでなければかなら発生はっせいする事象じしょうにより例外れいがいきることもあるほか、Rubyでは例外れいがい処理しょり関係かんけいなく大域たいいき脱出だっしゅつおこな制御せいぎょ構造こうぞう用意よういされている[13]

Smalltalkでも例外れいがいはエラー処理しょり以外いがい通知つうちとして使つかわれる。Smalltalkの例外れいがい (Exception) はエラー (Error) と通知つうち (Notification) からなり、EOFの通知つうちやスレッドあいだ終了しゅうりょう通知つうちとう使つかわれている。またSmalltalkは検索けんさくした結果けっかつからなかった場合ばあいもどとしてnil (null) をかえさない傾向けいこうがあり、つからなければ例外れいがいげる。ただし単純たんじゅん例外れいがい処理しょりというパターンがあり、つからない場合ばあいでも例外れいがい構文こうぶん使つかわず安全あんぜん回復かいふくする手段しゅだん用意よういしている。

通知つうち例外れいがいにはエラー例外れいがいことなる特徴とくちょうてきてんがある。通知つうちげた場合ばあいは、エラーとことなり補足ほそくしなければ処理しょり中止ちゅうしせずそのまま続行ぞっこうとなる。

もど例外れいがい

[編集へんしゅう]

例外れいがい処理しょり例外れいがいオブジェクト)をサポートしないCなどの言語げんごでは、従来じゅうらいから関数かんすうサブルーチン)のもどによってその関数かんすう処理しょり)の成否せいひ判定はんていする方法ほうほうがとられてきた。慣例かんれいてきに、関数かんすうもどを32ビット整数せいすうなどで宣言せんげんして、関数かんすう成功せいこうした場合ばあい0かえし、失敗しっぱいした場合ばあいはエラーコードとしてなんらかの負数ふすうかえすことがおお[14][15]。さらに簡略かんりゃくして、成否せいひ結果けっか真偽しんぎ1/0でかえすだけにすることもある。もどがポインタがたである場合ばあいは、成功せいこうした場合ばあい有効ゆうこうなポインタすなわちNULLをかえし、失敗しっぱいした場合ばあい無効むこうなポインタすなわちNULLをかえすのが通例つうれいである。標準ひょうじゅんライブラリ各種かくしゅAPIでは、詳細しょうさいつたえるエラーコードを別途べっとerrnoのようなグローバル変数へんすう格納かくのうすることもある。かくエラーコードによって失敗しっぱい原因げんいん定義ていぎしておき、がわ原因げんいん判定はんていする。

このようなもどによる処理しょり成否せいひ判定はんていには下記かきのような問題もんだいてんがある。

  1. もど無視むしできるため、さきでエラーが発生はっせいしても通常つうじょうどお処理しょり継続けいぞくするプログラムを記述きじゅつできてしまう。
  2. エラーコードはたいてい32ビットの整数せいすうでしかないため、それ以上いじょう詳細しょうさい情報じょうほうたとえば具体ぐたいてき原因げんいんおよび異常いじょう発生はっせい個所かしょなどをしめすエラーメッセージ)を付加ふかすることができない。
    直前ちょくぜんのエラー情報じょうほうをグローバル変数へんすう格納かくのうする設計せっけいは、マルチスレッド対応たいおうさい別途べっとスレッドローカルストレージ必要ひつようとなる。
  3. もど毎回まいかいチェックする判定はんていぶん記述きじゅつするのが煩雑はんざつである。
  4. もど正常せいじょうけい異常いじょうけい(エラー判定はんていよう)とを混在こんざいさせる、あるいは正常せいじょうけい異常いじょうけいとでもど区別くべつがつかない関数かんすうは、関数かんすう結果けっかもどしきなかでそのまま使つかえなくなってしまう。

3. に関連かんれんする問題もんだいとして、もど正常せいじょうけい結果けっか取得しゅとく使つかえないため引数ひきすう処理しょり結果けっか取得しゅとくよう使つか関数かんすうインターフェイスおよびがわのコードが複雑ふくざつするという問題もんだいがある。

bool countPositiveElements(const double x[], int inNumberOfElements, int* outNumberOfElements) {
    if (x == NULL || inNumberOfElements <= 0 || outNumberOfElements == NULL) {
        return false; // 異常いじょう終了しゅうりょう
    }
    *outNumberOfElements = 0;
    for (int i = 0; i < inNumberOfElements; ++i) {
        if (!isnan(x[i]) && x[i] > 0) { (*outNumberOfElements)++; }
    }
    return true; // 正常せいじょう終了しゅうりょう
}

4.の問題もんだいでは関数かんすう結果けっかをいったんローカル変数へんすう格納かくのうすることなくつぎ関数かんすう引数ひきすうにそのまましきとしてわたすようなこともできなくなる。たとえば下記かきのC言語げんごれいでは、atof()関数かんすうもど正常せいじょうけい異常いじょうけいとで区別くべつがつかない仕様しようのため、対象たいしょうフォーマットがい不正ふせい入力にゅうりょくがあっても検知けんちできず処理しょり継続けいぞくしてしまう。例外れいがい使つかわずにこの問題もんだい対処たいしょするには、正常せいじょうけい異常いじょうけいとを区別くべつできるようにするために、関数かんすう実装じっそうおよびインターフェイスが複雑ふくざつすることを許容きょようしなければならない。

#include <stdio.h>
#include <stdlib.h>

double addAsDouble(const char* x, const char* y) {
    return atof(x) + atof(y);
}

int main(void) {
    printf("%f\n", addAsDouble("1", "2"));
    printf("%f\n", addAsDouble("x", "y")); // 変換へんかんおよび加算かさん結果けっかは0となるが、意味いみ
}

一方いっぽう文字もじれつから数値すうちへの変換へんかん失敗しっぱいした場合ばあい例外れいがいげるライブラリを言語げんごでは、メインロジックに関係かんけいのないコードを挿入そうにゅうすることなく、正常せいじょうけい異常いじょうけいとを簡潔かんけつかつ明確めいかく区別くべつできる。下記かきはC#によるれいである。

using System;

public class Test
{
    public static double AddAsDouble(string x, string y)
    {
        return double.Parse(x) + double.Parse(y);
    }

    public static void Main()
    {
        try
        {
            Console.WriteLine(AddAsDouble("1", "2"));
            Console.WriteLine(AddAsDouble("x", "y")); // 例外れいがいがスローされ、処理しょり継続けいぞくされない。
        }
        catch
        {
        }
    }
}

べつれいとして、たとえばしゅ記憶きおく領域りょういき容量ようりょうやファイル容量ようりょう取得しゅとくする関数かんすう設計せっけいするさい結果けっか符号ふごうなし整数せいすうがた (非負ひふすう) のもどかえすようにめた場合ばあいもどでエラー判定はんていようかえすことができない。この場合ばあいerrnoのようなグローバル変数へんすうもしくは別途べっと用意よういした関数かんすう引数ひきすう経由けいゆでエラーコードをかえして、がわ判定はんていする必要ひつようがある。たとえばWindows APIのGetFileSize()関数かんすうもどでファイルサイズをかえすが、混合こんごうした設計せっけいとなっており、エラーが発生はっせいした場合ばあい-1かえす。しかしもどかたDWORDつまり符号ふごうなし32ビット整数せいすうがたであるため、実際じっさいには0xFFFFFFFF返却へんきゃくされる。これは本来ほんらい正常せいじょうとしてありうるであり、異常いじょうけいとの区別くべつかないため、エラーによる結果けっかだったかどうかを判定はんていするにはGetLastError()関数かんすうしが別途べっと必要ひつようになっている[16]。なおGetFileSizeEx()関数かんすう成否せいひもどで、正常せいじょうけい出力しゅつりょく引数ひきすうかえ設計せっけいとなっており、GetFileSize()関数かんすう代替だいたいとして推奨すいしょうされている[17]。また、C言語げんごにおいて身近みぢかれいとしてはmallocおよびcallocrealloc関数かんすうがあげられる。これらは確保かくほ要求ようきゅうする容量ようりょうとして0を指定していしたときC言語げんご規格きかくとしてNULLをかえしていと定義ていぎされている。[18]このためこれらの関数かんすうもどでは記憶きおく空間くうかん容量ようりょう不足ふそく引数ひきすうに0を指定していしたか判断はんだんできずけのためにerrno調しらべるか引数ひきすう調しらべる必要ひつようがある。C++において同等どうとうのnew演算えんざんではこのてん容量ようりょう不足ふそくのときだけ例外れいがいげることによって改善かいぜんしている。

言語げんごレベルでの例外れいがい処理しょりはこれらの欠点けってん解消かいしょうし、例外れいがい確実かくじつに、かつ統一とういつてき処理しょりする目的もくてき導入どうにゅうされたものとえる。

回復かいふく処理しょり

[編集へんしゅう]

記憶きおく領域りょういき枯渇こかつ

[編集へんしゅう]

処理しょりちゅう使用しよう可能かのう記憶きおく領域りょういき枯渇こかつした場合ばあい回復かいふく比較的ひかくてき単純たんじゅんである。

  1. 大量たいりょうデータをもうとした
  2. システム全体ぜんたい短期たんきてき記憶きおく領域りょういき枯渇こかつ
  3. システム全体ぜんたい長期ちょうきてき記憶きおく領域りょういき枯渇こかつ

記憶きおく領域りょういき原因げんいんとして上記じょうきかんがえられるがGUIプログラムのイベント処理しょりであれば3以外いがい状況じょうきょうから回復かいふくできる。1,2どちらも現在げんざい実行じっこうちゅう処理しょり中断ちゅうだんして処理しょり使つかった記憶きおく領域りょういき解放かいほうすればプロセスを継続けいぞくできる可能かのうせいがある。とくに2の状況じょうきょうであればシステムの記憶きおく領域りょういき使用しようじょうきょう回復かいふくって再度さいどおな処理しょり実行じっこうすることができる。

CUIの場合ばあいでかつ複数ふくすうのファイルを処理しょりしているような場合ばあい1の状況じょうきょうから回復かいふくすることができる。枯渇こかつ発生はっせいしただい容量ようりょうファイルの処理しょり無理むりでもそのしょう容量ようりょうファイルは処理しょりできる可能かのうせいがある。

つぎにSmalltalkによる回復かいふく処理しょりれいしめす:

| window textBox filePath open notifyArea |

"ファイルの失敗しっぱい通知つうちする部品ぶひん"
notifyArea := LabelStringMorph new.

"ファイルをひらくための部品ぶひん"
textBox := TextMorph new.
filePath := TextMorph new.
open := SimpleButtonMorph new.

"ボタンをクリックしたらファイルをんでテキストボックスに表示ひょうじできるようにする"
open
	on:     #click
	send:   #value
	to:
    [
    	[
    		filePath contents asFile withReadStreamDo:
    		[ :readStream |
    			textBox contents: readStream contents.
    		]
    	]
    		"
    		記憶きおく領域りょういき枯渇こかつした場合ばあい回復かいふく処理しょり
    		処理しょり中断ちゅうだんしたうえ、できるだけ資源しげん解放かいほうしたのち使用しようしゃ記憶きおく領域りょういき解放かいほううながす。
    		例外れいがい発生はっせいしてから例外れいがい捕捉ほそくするまでにいくふんかの記憶きおく領域りょういき解放かいほうされる、
    		解放かいほうゆとりができていれば回復かいふくできるが、ゆとりが場合ばあい回復かいふくできなくなる場合ばあいもある。
    		"
    		on: AllocationFailure
    		do:
    		[
    			ObjectMemory compact.  "ガーベッジコレクターによる解放かいほう"
    			textBox contents: ''. "途中とちゅうまでんでしまった文字もじれつ解放かいほう"
    			ObjectMemory compact.  "textBox contentsぶん解放かいほう"
    			notifyArea text: '記憶きおく領域りょういき枯渇こかつしているためファイルをけませんでした。のプログラムを終了しゅうりょうしてから再度さいど実行じっこうしてください。'
    		].
    ].

"ファイルを表示ひょうじするテキストボックスとファイルのみに必要ひつよう各種かくしゅ部品ぶひんんだWindowを表示ひょうじする"
window := SystemWindow new.
window
	addMorph: textBox;
	addMorph: filePath;
	addMorph: open;
	addMorph: notifyArea;
	openInWorld.

例外れいがいのネスト

[編集へんしゅう]

ある例外れいがい処理しょりちゅうに、もとのものとはべつ例外れいがい発生はっせいする場合ばあいがある。これを例外れいがいのネスト()とぶ。例外れいがいのネストの処理しょり例外れいがい処理しょり設計せっけい実装じっそう複雑ふくざつにするため、どの範囲はんいまでネストをゆるすかやどのような処理しょりたいしては例外れいがいゆるさないかがしばしば問題もんだいとなる。

言語げんご仕様しようとして実装じっそうされている例外れいがいにあっては、ネストのレベルは一般いっぱんには制限せいげんされていない。この場合ばあいおな例外れいがいかえ発生はっせいすることにより無限むげんループにおちいおそれがある。そのような状況じょうきょうへの対策たいさく設計せっけいしゃ実装じっそうしゃ責任せきにんとなる。

べつ抽象ちゅうしょうレベルとして、OSやCPUの例外れいがい処理しょり例外れいがいそなえた準備じゅんび複雑ふくざつすることをふせぐため、ネストレベルに制限せいげんをかける場合ばあいおおい。典型てんけいてきれいがページフォルトで、ユーザプロセスでのページフォルトはゆるすが、それを処理しょりするカーネルにたいしてはページフォルトをゆるさないことにより例外れいがい処理しょり簡単かんたんしている。また、CPUでは例外れいがい発生はっせいしハンドラを実行じっこうしようとしたさい、スタックオーバーフローに起因きいんするページフォルトなどさらなる例外れいがい発生はっせいすることがある。これはダブルフォルト英語えいご: Double faultばれ、専用せんようのハンドラやスタックなど一般いっぱんてき例外れいがいよりもさらに複雑ふくざつ設定せってい処理しょりようする。ダブルフォルトを処理しょりしようとしてさらに例外れいがい発生はっせいしてしまうとトリプルフォルト英語えいご: Triple faultとなり、現実げんじつてき処理しょり困難こんなんとなるためリセット処理しょりおこな実装じっそうおおい。

参照さんしょう

[編集へんしゅう]
  1. ^ a b だい 5 しょう 例外れいがい処理しょり (C++ プログラミングガイド)”. docs.oracle.com. 2019ねん10がつ26にち閲覧えつらん
  2. ^ a b IPA ISEC セキュア・プログラミング講座こうざ:C/C++言語げんごへん だい6しょう フェイルセーフ:体系たいけいだてたエラーハンドリング”. www.ipa.go.jp. 2019ねん10がつ26にち閲覧えつらん
  3. ^ a b エラー処理しょりをパターンにはめよう”. Codezine. 2019ねん10がつ26にち閲覧えつらん
  4. ^ Bjarne Stroustrup. “Appendix E: Standard-Library Exception Safety in "The C++ Programming Language" (3rd Edition).Addison-Wesley, ISBN 0-201-88954-4”. 2013ねん5がつ1にち閲覧えつらん
  5. ^ Exception-Safety in Generic Components”. 2013ねん5がつ1にち閲覧えつらん
  6. ^ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1997/N1077.asc
  7. ^ /EH (例外れいがい処理しょりモデル)
  8. ^ ただし、例外れいがい処理しょりちゅうにもう一度いちどべつのデストラクタから例外れいがい発生はっせいしてしまうと復帰ふっきできなくなるため、デストラクタから例外れいがい発生はっせいさせるべきではないとされる。
  9. ^ 例外れいがい指定していは、 C++関数かんすうによって伝達でんたつされる例外れいがい種類しゅるいについてプログラマが意図いとしたものをしめ言語げんご機能きのうです。 Microsoft Docs Visual C++
  10. ^ C++17ではこの動的どうてき例外れいがい仕様しよう削除さくじょされる。C++日本語にほんごリファレンス
  11. ^ class StopIteration Ruby 1.9.3 リファレンスマニュアル(2013ねん10がつ7にち閲覧えつらん)。
  12. ^ 例外れいがい Python 2.7ドキュメンテーション(2013ねん10がつ7にち閲覧えつらん)。
  13. ^ module function Kernel.#throw Ruby 1.9.2 リファレンスマニュアル(2013ねん10がつ7にち閲覧えつらん)。
  14. ^ たとえばCOMではメソッドのもどとして、MAKE_HRESULT()マクロをもちいてHRESULTコードを定義ていぎするが、異常いじょうけい負数ふすうとなる。
  15. ^ CUDAのように列挙れっきょがた定義ていぎしたせいかずをエラーコードとして使用しようするライブラリもある。CUDA Runtime API :: CUDA Toolkit Documentation
  16. ^ GetFileSize 関数かんすう
  17. ^ GetFileSize function (Windows)
  18. ^ C言語げんご規格きかくのドラフト”. 2018ねん11月21にち閲覧えつらん

関連かんれん項目こうもく

[編集へんしゅう]