例外処理
Posted feedbacks - Nested
Flatten HiddenRubyではbegin-rescure-ensure-endを使用します。
see: Rubyリファレンスマニュアル
1 2 3 4 5 6 7 8 9 10 | begin
# 処理本体はここに記述します
raise "サンプル例外です。"
rescue => e
puts "例外が発生しました。(「#{e.message}」)"
else
puts "例外が発生しなかった場合に実行されます。"
ensure
puts "例外の発生如何に関わらず実行されます。"
end
|
perlには例外用の構文はありませんが,evalを使用して処理するのが一般的です。
1 2 3 4 5 | eval {
# 処理本体はここに記述
die "サンプルエラーです。";
};
print "例外が発生しました。(「$@」)\n" if ($@);
|
RにはJavaライクな例外処理が実装されています。 > tryCatch(expr(1), error=e.handler, finally=f.handler()) [1] "finished" <simpleError: Exception> > tryCatch(expr(0), error=e.handler, finally=f.handler()) [1] "not error" [1] "finished"
1 2 3 4 5 6 7 8 9 10 11 | expr <- function(n=1){
if(n==1){
stop(simpleError("Exception"))
}
print("not error")
}
e.handler <- function(e) e
f.handler <- function() print("finished")
tryCatch(expr(1), error=e.handler, finally=f.handler())
tryCatch(expr(0), error=e.handler, finally=f.handler())
|
以下の2要素を組み合わせました。 - エラーが起きた時点で実行を中断 → set -e - それ(とシグナル)を捕捉 → trap、サブシェル $ sh q245.sh beginning of program begenning of foo begenning of bar Catch! end of program
see: 例外処理 - Wikipedia
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/bin/sh
bar() {
echo 'begenning of bar'
[ 1 = 2 ] # raise error
echo 'end of bar'
}
foo() ( # () runs subshell
echo 'begenning of foo'
# catch
set -e
trap 'echo "Catch!"' EXIT
bar
echo 'end of foo'
)
echo 'beginning of program'
foo
echo 'end of program'
|
Limboでは処理ブロックの後にexceptionブロックを つけることで例外処理が実現できるそうです。 例外処理ブロックはcase文と似た構文で、 "要因" => の後にその要因に対応する処理を書きます。 要因は out of memory zero divide 等が指定でき、*でワイルドカードが使えるようです。
see: Inferno's INTRO(2):
1 2 3 4 5 6 7 | {
# 処理本体
} exception e {
# 例外処理ブロック
"*" =>
# 処理内容
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | using System;
class P
{
static void Main(string[] args)
{
int a;
string str;
Console.WriteLine("逆数を求めます。整数を入力してください。");
str = Console.ReadLine();
try
{
a = (int)double.Parse(str);
Console.WriteLine("1 / {0} = {1}", str, 1.0 / a);
}
catch (FormatException)
{
Console.WriteLine("{0}は整数として有効ではありません。", str);
}
catch (DivideByZeroException)
{
Console.WriteLine("0では割れません。");
}
}
}
|
javaではtry-catch-finallyを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class ExTest {
public static void main( String[] args ) {
try {
throw new Exception();
} catch ( Exception e ) {
System.out.println( "例外が発生しました。" );
// スタックトレースを表示する。
e.printStackTrace();
} finally {
System.out.println( "必ず実行されます。" );
}
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | component doukaku245
export Executable
object NewException extends Exception
toString(): String = "Exception occured!"
end
run(args: String...): () = do
try
throw NewException
catch e
NewException => fail(e.toString())
finally
println("End of Exception test.")
end
end
end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <iostream>
#include <vector>
int main()
{
try
{
std::vector<int> v(2); //要素数2つ
std::cout << "3つ値を入力してください。" << std::endl;
std::cin >> v.at(0);
std::cin >> v.at(1);
std::cin >> v.at(2); //いや、そんなにないですって
}
catch (std::exception const& e)
{
std::cout << e.what() << std::endl;
}
}
|
C言語、ただしシグナルやsetjmpではありません。Windowsの構造化例外処理 (SEH) です。
例外を投げるにはRaiseException関数を呼ぶ方法もありますが、今回はCPUに例外を発生させました。
_exceptの丸括弧の中の式では、例外をキャッチするか否かを指定する値を指定します。filterexception関数内で、判定を行っています。ちなみに、今回使いませんでしたが、EXCEPTION_CONTINUE_EXECUTIONという__exceptブロック{}を実行せず、例外が発生した場所から実行再開するという指定もあります。
また、GetExceptionCodeの代わりにGetExceptionInformationを使うと詳しい情報の入ったEXCEPTION_POINTERS構造体(へのポインタ)が得られます。RaiseExceptionと組み合わせればC++などのようなオブジェクトの引き渡しを模倣できるはずです。
see: C と C++ での例外処理、第 2 部
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <windows.h>
#include <stdio.h>
int filter_exception(DWORD exceptionCode)
{
return exceptionCode == EXCEPTION_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH;
}
int main(void)
{
__try
{
int* p = NULL;
*p = 42; // ぬるぽ
}
__except(filter_exception(GetExceptionCode())) //例外をキャッチして処理する
{
fputs("ガッ!\n", stderr);
}
return 0;
}
|
1 2 3 4 5 6 7 8 9 | def hoge():
arr = []
return arr[100]
try:
hoge()
except Exception, e:
print('hoge() faild')
print(e)
|
HSPには例外処理機構が無いので、マクロで実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #define global try %tExcepHandling %i0 %i0 %i0 %i0 if (1)
#define global end_try %tExcepHandling *%p1 : %o0 %o0 %o0 %o0
#define global catch_list %tExcepHandling \
if (0) : *%p : %p3 = 0
#define global TEMP_CATCH(%1,%2) %tExcepHandling \
if ( %p3 ) { goto *%p1 } else { %p3 = 1 }\
} if (%1) { %2 = THREW_VALUE
#define global ctype catch(%1,%2=THREW_VALUE) %tExcepHandling \
TEMP_CATCH ( vartype(THREW_VALUE) == vartype("%1") ), %2
#define global ctype finally(%1=THREW_VALUE) %tExcepHandling \
TEMP_CATCH 1, %1
#define global throw(%1) %tExcepHandling \
THREW_VALUE = %1 : goto *%p
#define global try_break %tExcepHandling goto *%p1
#define global THREW_VALUE %tExcepHandling %p2
// サンプル・スクリプト
#if 1
randomize
repeat
wait 50
try {
// メイン処理、この中でしか throw できない。
switch ( rnd(3) )
case 0 : throw 2147483647 : swbreak
case 1 : throw "Hello, world!" : swbreak
case 2 : throw 3.141592 : swbreak
swend
} catch_list {
// throw されたらここに来る。
catch (int, x)
mes "int\t: "+ x
catch(str)
mes "str\t: \""+ THREW_VALUE +"\""
finally()
mes "final\t: "+ THREW_VALUE
} end_try
// catch_list を抜けるとここに来る
loop
stop
#endif
|
ScalaはJavaと同じくtry-catch-finallyとなりますが,例外の振り分けにcaseによるマッチングを使う様になっている所がらしいでしょうか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | object ExceptionSample {
def main(args:Array[String]):Unit = {
try {
println("処理本体")
args.size match {
case 0 => throw new IllegalArgumentException("引数が指定されていません")
case 1 => printf("引数: %s\n", args.first)
case _ => throw new Exception("引数の指定が不正です")
}
} catch {
case e:IllegalArgumentException => printf("例外発生(「%s」)\n", e.getMessage)
case e => e.printStackTrace
} finally {
println("例外の発生如何に関わらず実行")
}
}
}
|
以下のjavaの投稿を参考に、 groovy風に書き換えてみました。 どう書く?org 8769 nattou_curry: javaではtry-catch-fina...(例外処理) - 投稿の詳細 <http://ja.doukaku.org/comment/8769/>
1 2 3 4 5 6 7 8 | try {
throw new Exception()
} catch ( e ) {
println( "例外が発生しました。" )
e.printStackTrace()
} finally {
println( "必ず実行されます。" )
}
|
Smalltalk では、例外処理は #on:do: を、後処理は #ensure: を用います。
1 2 3 4 5 | [1/0]
on: ZeroDivide
do: [:ex | Float infinity] "#=> Infinity"
[self error: 'エラー発生'] ensure: [Transcript cr; show: '必ず実行']
|
1 2 3 4 5 6 7 8 9 | try:
# 処理本体はここに記述します
raise Exception("サンプル例外です。")
except Exception, e:
print "例外が発生しました。(「%s」)" % e
else:
print "例外が発生しなかった場合に実行されます。"
finally:
print "例外の発生如何に関わらず実行されます。"
|
InstallShield Scriptです。 InstallShield Scriptは Windowsアプリケーション用のインストーラーを作成するための 言語ですが、ヘルプを見ていて意外にも(?) 例外処理をサポートしていることに気がつき ました。 以下はヘルプに載っている内容を手直ししたものですが、この処理だと try ... catchを 利用するメリットは... ありませんよね。(すみません。) # InstallShield Profesional 7.01でビルドして動作を確認しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include "ifx.h"
#include "ErrorsObj.h"
NUMBER n;
STRING p;
program
_:
AskText("ファイルのパスを入力してください。", "", p);
try
if (!Is(FILE_EXISTS, p)) then
Err.Raise(OBJ_STATUS_FILENOTFOUND);
endif;
MessageBox("指定されたファイルは存在します。", INFORMATION);
catch
n = Err.Number;
switch (n)
case OBJ_STATUS_FILENOTFOUND :
MessageBox("指定されたファイルは存在しません。", WARNING);
default :
MessageBox(Err.Description, SEVERE);
endswitch;
endcatch;
if (AskYesNo("パスを再入力しますか? ", YES) = YES) goto _;
abort;
endprogram
|
1 2 3 4 5 6 7 8 9 10 11 | -module(exception).
-export([exception/0]).
f() -> throw("exception").
exception() ->
X = try f()
catch
throw : Y -> "catch : " ++ Y
end,
io:format(X).
|
Haskellの例外処理は世代がいくつかあるみたいですが、Control.Exceptionのやつを使ってみました…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | module Main where
import Prelude hiding (catch)
import Control.Exception
thrower :: IO ()
thrower = do
putStrLn "thrower throws exception"
throwIO (ErrorCall "can't call this")
catcher :: ErrorCall -> IO ()
catcher e = putStrLn $ "caught \"" ++ (show e) ++ "\" exception."
main = catch thrower (catcher)
|
いろいろな例外。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | object ExceptionSample {
def main(args : Array[String]) : Unit = {
try{
val a = Array(1,2,3)
println (a(5)) // --> java.lang.ArrayIndexOutOfBoundsException
val f=new java.io.FileReader("\\.txt") // -->java.io.FileNotFoundException
val re = "[A-Za-0]".r //--> java.util.regex.PatternSyntaxException
()
}catch{
case e:java.io.IOException => println( "IO Err "+e)
case e:Exception => println ("Err "+e)
case _ => println ("Unknown error")
}finally{
println ("Done")
}
}
}
|
with部分で例外の種類を特定するのにパターンマッチを使用する点が特徴です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #light
open System
exception Original of string * string // F#例外の定義
type Example() =
member this.Func() =
Original("ユーザー定義例外", "例外発生") |> raise
interface IDisposable with
member this.Dispose() =
printfn "資源解放"
try
use ex = new Example()
ex.Func()
with
| :? NullReferenceException as e -> // .NET例外の捕捉
printfn "ぬるぽ %s" e.Message
rethrow()
| Original(name, msg) -> // F#例外の捕捉
printfn "例外名:%s メッセージ:%s" name msg
|



turugina
#8712()
Rating2/2=1.00
例外処理の適当なサンプルを書いてください。
但し、言語によって例外処理がサポートされている場合はそれを利用してください。
see: 例外処理
[ reply ]