perl:为什么Devel :: Refcount :: refcount和Devel :: Peek :: SvREFCNT不一致?

时间:2012-07-05 12:38:20

标签: perl

我正在阅读How can I access the ref count of a Perl hash?,并建议Devel::Refcount::refcountDevel::Peek::SvREFCNT

但他们没有返回相同的引用计数。那是为什么?

这是perldoc Devel::Refcount的修改示例:

use Devel::Peek;
use Devel::Refcount;

my $anon = [];

printf "Anon ARRAY $anon has %d/%d reference\n",
    Devel::Refcount::refcount($anon),
    Devel::Peek::SvREFCNT($anon);

my $otherref = $anon;

printf "Anon ARRAY $anon now has %d/%d references\n",
    Devel::Refcount::refcount($anon),
    Devel::Peek::SvREFCNT($anon);

打印出来:

Anon ARRAY ARRAY(0x8b10818) has 1/1 reference
Anon ARRAY ARRAY(0x8b10818) now has 2/1 references

注意最后2/1的差异......

(如果事实证明我没有做一些愚蠢的事情,我会在How can I access the ref count of a Perl hash?添加一个链接到这里)

2 个答案:

答案 0 :(得分:8)

我不能说我已经完成了所有这些,但你的问题在Devel::Refcount perldoc

中得到了显着的回答。
  

与SvREFCNT比较

     

此函数与Devel :: Peek :: SvREFCNT的不同之处在于,SvREFCNT()给出了传递它的SV对象本身的引用计数,而refcount()给出了指向的对象的计数。这允许它给出任何指示对象的计数(即ARRAY,HASH,CODE,GLOB和Regexp类型)。

     

考虑以下示例程序:

 use Devel::Peek qw( SvREFCNT );
 use Devel::Refcount qw( refcount );

 sub printcount
 {
    my $name = shift;

    printf "%30s has SvREFCNT=%d, refcount=%d\n",
       $name, SvREFCNT($_[0]), refcount($_[0]);
 }

 my $var = [];

 printcount 'Initially, $var', $var;

 my $othervar = $var;

 printcount 'Before CODE ref, $var', $var;
 printcount '$othervar', $othervar;

 my $code = sub { undef $var };

 printcount 'After CODE ref, $var', $var;
 printcount '$othervar', $othervar;
  

这会产生输出

            Initially, $var has SvREFCNT=1, refcount=1
      Before CODE ref, $var has SvREFCNT=1, refcount=2
                  $othervar has SvREFCNT=1, refcount=2
       After CODE ref, $var has SvREFCNT=2, refcount=2
                  $othervar has SvREFCNT=1, refcount=2
  

在这里,我们看到SvREFCNT()将传入的SV对象的引用数分别计算为标量值 - $ var或$ othervar,而refcount()计算指向引用的引用值的数量object - 在这种情况下是匿名ARRAY。

     

在构造CODE引用之前,$ var和$ othervar的SvREFCNT()都是1,因为它们仅存在于当前词法填充中。匿名ARRAY的refcount()为2,因为$ var和$ othervar都存储了对它的引用。

     

构造CODE引用之后,$ var变量现在的SvREFCNT()为2,因为它也出现在新的匿名CODE块的词法填充中。

答案 1 :(得分:4)

Devel::Refcount::refcount($anon)返回$anon引用的引用计数。

数组由$anon$otherref引用:2


Devel::Peek::SvREFCNT($anon)会返回$anon本身的引用计数。

标量由它所在的垫子引用:1

Devel :: Peek似乎没有提供获取数组,散列等的引用计数的方法。


$ perl -MDevel::Peek -E'my $aref2 = my $aref1 = []; Dump($aref1);'
SV = IV(0x99eee34) at 0x99eee38
  REFCNT = 1                    <---- Devel::Peek::SvREFCNT
  FLAGS = (PADMY,ROK)
  RV = 0x99d57d0
  SV = PVAV(0x99d6778) at 0x99d57d0
    REFCNT = 2                  <---- Devel::Refcount::refcount
    FLAGS = ()
    ARRAY = 0x0
    FILL = -1
    MAX = -1
    ARYLEN = 0x0
    FLAGS = (REAL)

Perl提供了一个名为Internals::SvREFCNT的半支持内置函数,可用于标量,数组和哈希。

Internals::SvREFCNT(@$anon)会返回@$anon本身的引用计数。

数组由$anon$otherref引用:2

以上仅适用于标量,数组和散列,您需要使用正确的标记。如果您只想传递任意引用,可以使用:

&Internals::SvREFCNT($anon) + 1返回$anon引用的引用计数。

数组由$anon$otherref引用:2