2011-07-17 23 views
4

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

#!/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_inc(); 
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 

给出:

inc: 1 
noinc: 1 

谁能帮助我了解为什么这种行为这种方式?

回答

4

当你调用SvREFCNT($arrayref)你得到的引用计数数组引用,而不是阵列,它的引用。 newRV_inc递增参考计数array,并且newRV_noinc没有。但是这对arrayref的引用计数没有任何影响。 (我不认为你可以通过Devel :: Peek获得arrayref引用的数组的refcount。)

你看过perlguts: Reference Counts and Mortality的例子吗?

AV* array = newAV()创建具有为1的引用次数在make_arrayref_inc一个新的数组,newRV_inc增量,虽然创建新的SV(该数组引用)用的1。这一个引用计数到2导致内存泄漏,因为不这样做减量退出该功能之前,请提供array的退款。 Perl认为它有2个引用,但它确实只有1个引用,所以在解释器关闭之前它永远不会被垃圾回收。

这就是为什么您通常在代码中使用newRV_noinc,该代码返回对新创建值的引用。这比使用newRV_inc然后SvREFCNT_dec更有效。您可以将newRV_noinc视为将AV的所有权从array转移到arrayref

+0

谢谢@cjm,最后一段最后是我需要了解何时增加。虽然我敢打赌,在实践中,我将继续使用迄今为止我使用的“不破坏对象的最小增量”方法。 –