2013-02-25 24 views
3

如果我有一個StandardError實例,消息存儲在哪裏?Ruby異常實例在哪裏保存消息?

s = StandardError.new("hi") 
s.message       # => "hi" 
s.instance_variables    # => [] 
s.instance_variable_get(:@message) # => nil 
s.inspect       # => "#<StandardError: hi>" 

回答

3

在對Ruby和C進行了一些調查之後,我發現異常類設置了一個名稱爲mesg的實例變量。這不能在標準的Ruby運行時中訪問,因爲它不是以@開頭的。

可以添加一個Ruby擴展,它可以讓你獲取和設置不帶前綴@的實例變量。我不知道這可能有多危險。

I2C模塊:

#include "ruby.h" 

static VALUE rb_mIvar; 

static VALUE rb_ivar_iv_get(VALUE self, VALUE key) { 
    return rb_ivar_get(self, rb_to_id(key)); 
} 

static VALUE rb_ivar_iv_set(VALUE self, VALUE key, VALUE value) { 
    return rb_ivar_set(self, rb_to_id(key), value); 
} 

void Init_ivar() { 
    rb_mIvar = rb_define_module("Ivar"); 
    rb_define_method(rb_mIvar, "ivar_get", rb_ivar_iv_get, 1); 
    rb_define_method(rb_mIvar, "ivar_set", rb_ivar_iv_set, 2); 
} 

紅寶石用法:

$:.unshift('.') 
require 'ivar' 

Object.send(:include, Ivar) 

e = StandardError.new("foo") 

puts "Error message is: #{e.message}" # => e.message is "foo" 

e.ivar_set(:mesg, "bar") 

puts "Error message is: #{e.message}" # => e.message is now "bar" 

看到這個要點有完整的代碼我用來研究和實驗:https://gist.github.com/adamhunter/5041075

6

另外,請注意並非Ruby的所有部分都是用Ruby編寫的,特別是對於像Exception或StandardError這樣的非常基本的類。

通過查看Exception類的消息方法的來源,您可以找到答案(點擊然後轉到消息方法並使用小型放大鏡顯示源代碼)。這段代碼是C,而不是Ruby。

+0

感謝鏈接Exception類。我已經做了一些挖掘工作,以找出在C中處理這些細節的具體細節,並在此問題上發佈了我的結果。 – Adam 2013-02-26 19:06:53