设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 1492|回复: 4
打印 上一主题 下一主题

[已经解决] 为什么eval传入了__FILE__和__LINE__参数就能精确报错位置?

[复制链接]

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

跳转到指定楼层
1
发表于 2014-7-5 12:19:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 taroxd 于 2014-7-5 13:28 编辑

RUBY 代码复制
  1. class RPG::UsableItem::Damage
  2.   #--------------------------------------------------------------------------
  3.   # ● 根据参数执行计算公式
  4.   #--------------------------------------------------------------------------
  5.   def eval(a, b, v)
  6.     value = b.instance_eval Taroxd::Script.process(@formula),
  7.                             __FILE__, __LINE__
  8.     value > 0 ? value * sign : 0
  9.   end
  10. end


↑ 这是我的脚本。Taroxd::Script.process方法总之是对代码做一些修改(这也是我写这个脚本的原因之一;另一个原因是利用受伤者的上下文来eval),不用在意其中的内容。
就当是这样好了 def Taroxd::Script.process(formula); formula; end

在RGSS3内置脚本中,这个方法是被rescue的。也就是出错了会默默的把技能公式的计算结果归为0。我认为这是不好的特性。报错就是要报的准才行。

于是,我第一次尝试 value = b.instance_eval Taroxd::Script.process(@formula) ,并且刻意输入了会报错的技能公式。结果是:报错信息正确且完整,但报错在eval处,打开脚本编辑器,不会跳转到报错的位置
于是我又尝试了上面的代码,结果是:报错信息正确且完整,报错在真正出错的地方,打开脚本编辑器会跳转到报错的位置

所以我想问,这是什么原理?
传入 __FILE__, __LINE__ 能让eval产生什么样的效果?
VA的脚本编辑器的「跳转至报错位置」是怎么样的原理?

就代码而言,我的问题是解决了的。但是我想要弄清楚得以解决的原因。谢谢。

Lv1.梦旅人

梦石
0
星屑
117
在线时间
552 小时
注册时间
2012-8-18
帖子
1429
2
发表于 2014-7-5 13:12:08 | 只看该作者
摔文档1:http://www.cnblogs.com/darkbaby1 ... ming_file_line.html
摔文档2:http://stackoverflow.com/questio ... ean-in-ruby/2496240
摔文档3:http://www.kuqin.com/rubycndocument/man/stdlib_function.html

eval(expr[, binding[, fname[, lineno=1]]])

    把字符串expr当作Ruby程序来运行并返回其结果。若给第二参数传递Proc对象或Binding对象的话,将在生成该对象的环境中对字符串进行计算。请参考binding。

  1.     def foo
  2.       a = 1
  3.       binding
  4.     end

  5.     eval("p a", foo)  # => 1
  6.    
复制代码
若指定了fname 和 lineno的话,将假定字符串位于fname文件lineno行,并且进行编译。这时可以显示栈跟踪(stack trace)等信息。

评分

参与人数 1梦石 +1 收起 理由
taroxd + 1 认可答案

查看全部评分

我要填坑!我要背单词!我要学日语!我要每天锻炼!
好吧呵呵= =
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

3
 楼主| 发表于 2014-7-5 13:27:30 | 只看该作者
本帖最后由 taroxd 于 2014-7-5 13:51 编辑
无脑之人 发表于 2014-7-5 13:12
摔文档1:http://www.cnblogs.com/darkbaby1 ... ming_file_line.html
...


不对啊我和这例子不一样。

你给的例子是,在class_eval生成动态方法的时候传入了 __FILE__, __LINE__,因此可以追踪报错信息

但是我那个脚本只是单纯的执行啊。为什么传入了__FILE__之后报错的行数就会变掉呢

试验:

RUBY 代码复制
  1. # LINE 1
  2. def raise!
  3.   raise
  4. end
  5.  
  6. # eval 'raise!'
  7. # D:/Documents/workspace/test.rb:6:in `eval': D:/Documents/workspace/test.rb:3:in `raise!':  (RuntimeError)
  8. #     from (eval):1:in `<main>'
  9. #     from D:/Documents/workspace/test.rb:6:in `eval'
  10. #     from D:/Documents/workspace/test.rb:6:in `<main>'
  11.  
  12. # LINE 12
  13. # eval '
  14. # raise', binding
  15. # D:/Documents/workspace/test.rb:16:in `<main>': unhandled exception
  16. #     from D:/Documents/workspace/test.rb:14:in `eval'
  17. #     from D:/Documents/workspace/test.rb:14:in `<main>'
  18.  
  19. # LINE 19
  20. # eval 'raise', binding, __FILE__,
  21. # __LINE__
  22. # D:/Documents/workspace/test.rb:21:in `<main>': unhandled exception
  23. #     from D:/Documents/workspace/test.rb:20:in `eval'
  24. #     from D:/Documents/workspace/test.rb:20:in `<main>'
  25.  
  26. # LINE 26
  27. # instance_eval 'raise!'
  28. # D:/Documents/workspace/test.rb:27:in `instance_eval': D:/Documents/workspace/test.rb:3:in `raise!':  (RuntimeError)
  29. #     from (eval):1:in `<main>'
  30. #     from D:/Documents/workspace/test.rb:27:in `instance_eval'
  31. #     from D:/Documents/workspace/test.rb:27:in `<main>'
  32.  
  33. # LINE 33
  34. # instance_eval 'raise!', __FILE__,
  35. # __LINE__
  36. # D:/Documents/workspace/test.rb:3:in `raise!': unhandled exception
  37. #     from D:/Documents/workspace/test.rb:35:in `<main>'
  38. #     from D:/Documents/workspace/test.rb:34:in `instance_eval'
  39. #     from D:/Documents/workspace/test.rb:34:in `<main>'


总之加个 binding或者__FILE__, Ruby就会变得聪明?
我觉得就像37行报错一样,加了个__LINE__查找堆栈时,eval这个错误的记录就会记在35行。
但是caller_stack的最外层是如何受到 __FILE__,__LINE__的影响的呢?不传入__FILE__,就会报在eval上面;传入了,就会报在raise!上面
@无脑之人  你的解答告诉了我第37行的原理,但我想要的是第36行的报错原理

话说我没有在元编程啦233
还有,为什么RM的代码高亮不支持HERE DOCUMENT啊啊啊,害得我一直用%{}

点评

2333333抱歉了,这问题我解决不了,你可以去stackoverflow问问  发表于 2014-7-5 18:59
不对,我问题没有解决啊!!!  发表于 2014-7-5 18:54
写在脚本编辑器里,那颜色看着难受啦  发表于 2014-7-5 18:53
如果我知道怎么回事我就不摔文档了,我很少用eval  发表于 2014-7-5 18:46
其实是支持HEREDOC的但是默认用黑色显示(用你的Sublime去(?  发表于 2014-7-5 18:35
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv2.观梦者 (禁止发言)

梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
帖子
1839

开拓者

4
发表于 2014-7-6 21:51:40 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

5
 楼主| 发表于 2014-7-6 21:53:35 | 只看该作者
本帖最后由 taroxd 于 2014-7-7 08:13 编辑
晴兰 发表于 2014-7-6 21:51
https://rpg.blue/thread-249703-1-1.html


那么,instance_eval传入__FILE__参数,可以让backtrace第一个不被替换成instance_eval的原因是?

我翻了一翻源码,发现不传入file参数时,C实现中的file参数值为Qundef

顺着函数,我又找到了这样一段:
C 代码复制
  1. if ((fname = file) == Qundef) {
  2.             fname = rb_usascii_str_new_cstr("(eval)");
  3.         }


接下来我就不知道了……
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-9-25 17:21

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表