LoginSignup
5
1

More than 5 years have passed since last update.

Rubyで例外を発生させる

Posted at

特定の値を代入できないグローバル変数に代入

$~nilMatchDataのインスタンス以外を代入すると例外が発生します。

$ ruby -e '$~=1'
Traceback (most recent call last):
-e:1:in `<main>': wrong argument type Integer (expected MatchData) (TypeError)

おこられるリテラルを書く

$ ruby -e 'def Range.new(*); end; nil..false'
Traceback (most recent call last):
-e:1:in `<main>': bad value for range (ArgumentError)

例えばRange.new(nil, false)を実行すると同じように例外が発生しますが、newを上書きされてしまうと例外が発生しません。

def Range.new(*); end
Range.new(nil, false)
# => nil

リテラルで書くとRange.newを再定義していてもCのRange.new相当のC関数が直接呼ばれるため必ず例外を発生できます。

無限に再帰

def raise(_=raise)
end
raise
$ ruby -e 'def raise(_=raise); end; raise'
Traceback (most recent call last):
        11913: from -e:1:in `<main>'
        11912: from -e:1:in `raise'
        11911: from -e:1:in `raise'
        11910: from -e:1:in `raise'
        11909: from -e:1:in `raise'
        11908: from -e:1:in `raise'
        11907: from -e:1:in `raise'
        11906: from -e:1:in `raise'
         ... 11901 levels...
            4: from -e:1:in `raise'
            3: from -e:1:in `raise'
            2: from -e:1:in `raise'
            1: from -e:1:in `raise'
-e:1:in `raise': stack level too deep (SystemStackError)

こう定義するとTracePointのcallイベントが発生するため再帰呼出しをする前にreturnされてしまう可能性があります。

def raise
  raise
end
TracePoint.trace(:call) {|tp| tp.binding.eval("return nil") }
raise

引数で再帰すると大丈夫です。

メソッドの外でsuper

$ ruby -e 'super'
Traceback (most recent call last):
-e:1:in `<main>': super called outside of method (NoMethodError)

:x: raise

raiseはメソッドなので上書きされる可能性があります。

method(:raise)
# => #<Method: main.raise>
def raise; end
raise
# => nil

:x: catchせずにthrow

throwはメソッドなので上書きされる可能性があります。

method(:throw)
=> #<Method: main.throw>
def throw(*); end
throw :hi

:x: 存在しないローカル変数やメソッドを呼び出す

method_missingで回避されてしまう可能性があります。

class Object
  def method_missing(*)
    true
  end

  def respond_to_missing(*)
    true
  end
end

foo

:x: 未定義のクラス変数を参照

未定義かどうか調べる方法がなさそう

$ ruby -e '@@foo'
-e:1: warning: class variable access from toplevel
Traceback (most recent call last):
-e:1:in `<main>': uninitialized class variable @@foo in Object (NameError)

:x: 未定義の定数を参照

未定義かどうか調べる方法がなさそう

$ ruby -e 'Foo'
Traceback (most recent call last):
-e:1:in `<main>': uninitialized constant Foo (NameError)
5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1