了解newRV_inc vs newRV_noinc

Joe*_*ger 5 perl perlguts

在试图处理C级的参考时,我似乎无法弄清楚newRV_inc和之间的差异(在实践中)newRV_noinc.为此,我嘲笑了这个小Inline::C例子.

#!/usr/bin/env perl

use strict;
use warnings;

use Devel::Peek 'SvREFCNT';

my $arrayref_inc = make_arrayref_inc();
print "inc: ", SvREFCNT($arrayref_inc), "\n";

my $arrayref_noinc = make_arrayref_noinc();
print "noinc: ", SvREFCNT($arrayref_noinc), "\n";

use Inline C => <<'END_C';
SV* make_arrayref_inc () {
  AV * array = newAV();
  SV * arrayref = newRV_inc((SV *)array);

  return arrayref;
}

SV* make_arrayref_noinc () {
  AV * array = newAV();
  SV * arrayref = newRV_noinc((SV *)array);

  return arrayref;
}
END_C
Run Code Online (Sandbox Code Playgroud)

得到:

inc: 1
noinc: 1
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助我理解为什么这段代码会这样做?

cjm*_*cjm 5

当你调用时,SvREFCNT($arrayref)你得到的是arrayref的引用计数,而不是它引用的数组. newRV_inc增加引用计数array,而newRV_noinc不是.但这对参考计数没有任何影响arrayref.(我认为你不能得到带有Devel :: Peek的arrayref引用的数组的引用计数.)

您是否阅读了perlguts中的示例:参考计数和死亡率

AV* array = newAV()创建具有的1.在引用计数一个新的数组make_arrayref_inc,newRV_inc递增,为2,而与为1的引用次数创建一个新的SV(该数组引用)这引起了内存泄漏,因为你不递减array退出函数之前的引用计数.Perl认为它有2个引用,但它实际上只有1个,所以在解释器关闭之前它永远不会被垃圾收集.

这就是您通常newRV_noinc在代码中使用的原因,该代码返回对新创建的值的引用.它比使用更有效newRV_inc,然后SvREFCNT_dec.您可以newRV_noinc将AV的所有权转移arrayarrayref.