为什么我不能获得分配源信息?

时间:2016-02-17 20:53:44

标签: ruby

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。 Regxp

当我有一个正则表达式时,即使它没有被冻结,我也无法获得源信息:

obj = /foo/
obj.frozen? # => false
ObjectSpace.allocation_sourcefile(obj) # => nil
ObjectSpace.allocation_sourceline(obj) # => nil

为什么我不能从正则表达式获取源位置,即使它没有被冻结?

1 个答案:

答案 0 :(得分:2)

ObjectSpace.trace_object_allocations_start调用之前简单地分配了这两个对象,或者执行了此文件中的任何其他Ruby代码:

  • "foo".freeze已分配到compile time by rb_fstring()(最初也位于parse time

  • 在运行时额外分配"foo"只是因为内部obj = "foo"实际上与obj = "foo".dup相似。有关更多详细信息,请查看putstring YARV instructionrb_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]