1. 字符串
当我有一个非卡住非实习字符串时,我可以获得它的源位置(假设文件名是 foo_file.rb ):

require "objspace"
ObjectSpace.trace_object_allocations_start

obj = "foo"
ObjectSpace.allocation_sourcefile(obj) # => foo_file.rb
ObjectSpace.allocation_sourceline(obj) # => 4
当我有一个实习字符串时,源位置变得不可用(注意字符串文字后带有 freeze 的实习功能):
obj = "foo".freeze
ObjectSpace.allocation_sourcefile(obj) # => nil
ObjectSpace.allocation_sourceline(obj) # => nil
我可以确认这种不可用不是因为它被卡住,而是因为它被实习:
obj = "foo"
obj = obj.freeze
ObjectSpace.allocation_sourcefile(obj) # => foo_file.rb
ObjectSpace.allocation_sourceline(obj) # => 4
为什么我不能从一个实习字符串中获取源信息?
2. 正则表达式
当我有一个正则表达式时,即使它没有被卡住,我也无法获取源信息:
obj = /foo/
obj.frozen? # => false
ObjectSpace.allocation_sourcefile(obj) # => nil
ObjectSpace.allocation_sourceline(obj) # => nil
为什么即使没有卡住,我也无法从正则表达式中获取源位置?

最佳答案

这两个对象只是在 ObjectSpace.trace_object_allocations_start 调用或此文件中的任何其他 Ruby 代码执行之前分配的:

  • "foo".freeze 被分配在 compile time by rb_fstring() (最初也在 parse time )
  • "foo" 在运行时的额外分配发生只是因为内部 obj = "foo" 实际上类似于 obj = "foo".dup 。有关更多详细信息,请查看 putstring YARV instruction rb_str_resurrect() 函数的定义。
  • /foo/parse time by reg_compile() 分配。就是这样。这里没有重复,所以它总是同一个对象(虽然没有发生实习,但对某些人来说这可能是令人惊讶的行为):
    3.times.map{ "foo".object_id }.uniq         # => [21063740, 21063720, 21063700]
    3.times.map{ "foo".freeze.object_id }.uniq  # => [21064340]
    3.times.map{ /foo/.object_id }.uniq         # => [21065100]
    
  • 关于ruby - 为什么我无法获取分配源信息?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35467521/

    10-16 16:07
    查看更多