特定の値を代入できないグローバル変数に代入
$~
にnil
やMatchData
のインスタンス以外を代入すると例外が発生します。
$ 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)
raise
raise
はメソッドなので上書きされる可能性があります。
method(:raise)
# => #<Method: main.raise>
def raise; end
raise
# => nil
catchせずにthrow
throw
はメソッドなので上書きされる可能性があります。
method(:throw)
=> #<Method: main.throw>
def throw(*); end
throw :hi
存在しないローカル変数やメソッドを呼び出す
method_missing
で回避されてしまう可能性があります。
class Object
def method_missing(*)
true
end
def respond_to_missing(*)
true
end
end
foo
未定義のクラス変数を参照
未定義かどうか調べる方法がなさそう
$ 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)
未定義の定数を参照
未定義かどうか調べる方法がなさそう
$ ruby -e 'Foo'
Traceback (most recent call last):
-e:1:in `<main>': uninitialized constant Foo (NameError)