加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 叶子 于 2012-9-26 06:50 编辑
在Ace环境下,eval()里面抛出的异常通常都无法定位到正确的脚本与行号。测试脚本如下
def foo bar(5) end def bar end begin eval('foo') rescue Exception=>e p e p e.backtrace end `PAUSE`
def foo
bar(5)
end
def bar
end
begin
eval('foo')
rescue Exception=>e
p e
p e.backtrace
end
`PAUSE`
使用Ace运行结果:
#<ArgumentError: wrong number of arguments (1 for 0)>
["{0151}:9:in `eval'", "(eval):1:in `<main>'", "{0151}:9:in `eval'", "{0151}:9:in `<main>'", "ruby:in `eval'"]
使用ruby 1.9.3运行结果:
#<ArgumentError: wrong number of arguments (1 for 0)>
["eval_test.rb:9:in `eval'", "eval_test.rb:2:in `foo'", "(eval):1:in `<main>'", "eval_test.rb:9:in `eval'", "eval_test.rb:9:in `<main>'"]
可见ruby 1.9.3的stacktrace的第二个是出错的正确位置,而Ace缺失这个信息。
事件脚本党应该深有体会,因为事件运行脚本command_355就是eval(script)
所以有Ace下的获得异常正确位置的解决办法吗?
经过艰苦的讨论,得出一个不完美的解决方案
def wrap_trace_capture(script) " begin #{script} rescue Exception=>e true_backtrace = Marshal.load(Marshal.dump(e.backtrace)) e.define_singleton_method(:correct_backtrace) do e.backtrace.replace(true_backtrace) end raise e end " end begin eval(wrap_trace_capture('foo')) rescue Exception=>e p e p e.backtrace e.correct_backtrace if e.respond_to?(:correct_backtrace) raise e end
def wrap_trace_capture(script)
"
begin
#{script}
rescue Exception=>e
true_backtrace = Marshal.load(Marshal.dump(e.backtrace))
e.define_singleton_method(:correct_backtrace) do
e.backtrace.replace(true_backtrace)
end
raise e
end
"
end
begin
eval(wrap_trace_capture('foo'))
rescue Exception=>e
p e
p e.backtrace
e.correct_backtrace if e.respond_to?(:correct_backtrace)
raise e
end
有任何改进/建议么?
0回复,似乎没什么人在意这个颇消耗开发时间的问题..
放个即插即用版本好了
#============================================================================== # ■ EvalStackFix #------------------------------------------------------------------------------ # 修正eval中抛出的异常的backtrace不正确,进而导致脚本编辑器跳转不正确的问题 # 使用方法: # 直接插入脚本编辑器 # 放置位置应尽量靠近Main # 注意事项: # 本代码仅适用于RPG Maker Ace。相同的机制可应用于其他版本 #============================================================================== module EvalStackFix module_function #-------------------------------------------------------------------------- # ● 包装eval内容,截取正确的backtrace #-------------------------------------------------------------------------- def wrap(script) "begin #{script} # 上面一行没有缩进是因为script可能包含=begin关键字,而=begin前面不能有空格 rescue Exception=>e true_backtrace = Marshal.load(Marshal.dump(e.backtrace)) # deep clone e.define_singleton_method(:correct_backtrace) do e.backtrace.replace(true_backtrace) end raise e end" end end alias rgss_main_no_eval_stack_fix rgss_main def rgss_main(&proc) begin rgss_main_no_eval_stack_fix(&proc) rescue Exception=>e p e e.correct_backtrace if e.respond_to?(:correct_backtrace) p e.backtrace raise e end end alias eval_no_stack_fix eval def eval(script, *args) eval_no_stack_fix(EvalStackFix.wrap(script), *args) end
#==============================================================================
# ■ EvalStackFix
#------------------------------------------------------------------------------
# 修正eval中抛出的异常的backtrace不正确,进而导致脚本编辑器跳转不正确的问题
# 使用方法:
# 直接插入脚本编辑器
# 放置位置应尽量靠近Main
# 注意事项:
# 本代码仅适用于RPG Maker Ace。相同的机制可应用于其他版本
#==============================================================================
module EvalStackFix
module_function
#--------------------------------------------------------------------------
# ● 包装eval内容,截取正确的backtrace
#--------------------------------------------------------------------------
def wrap(script)
"begin
#{script}
# 上面一行没有缩进是因为script可能包含=begin关键字,而=begin前面不能有空格
rescue Exception=>e
true_backtrace = Marshal.load(Marshal.dump(e.backtrace)) # deep clone
e.define_singleton_method(:correct_backtrace) do
e.backtrace.replace(true_backtrace)
end
raise e
end"
end
end
alias rgss_main_no_eval_stack_fix rgss_main
def rgss_main(&proc)
begin
rgss_main_no_eval_stack_fix(&proc)
rescue Exception=>e
p e
e.correct_backtrace if e.respond_to?(:correct_backtrace)
p e.backtrace
raise e
end
end
alias eval_no_stack_fix eval
def eval(script, *args)
eval_no_stack_fix(EvalStackFix.wrap(script), *args)
end
|