5

在尝试处理 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

给出:

inc: 1
noinc: 1

谁能帮我理解为什么这段代码会这样?

4

1 回答 1

5

当您调用时,您将获得arrayrefSvREFCNT($arrayref)的引用计数,而不是它所引用的数组。 增加 的引用计数,但不增加。但这对 . 的引用计数没有任何影响。(我认为您无法使用 Devel::Peek 获取 arrayref 引用的数组的引用计数。)newRV_incarraynewRV_noincarrayref

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

AV* array = newAV()创建一个引用计数为 1 的新数组。在make_arrayref_inc中,newRV_inc将其递增到 2,同时创建一个引用计数为 1 的新 SV(arrayref)。这会导致内存泄漏,因为您array在退出函数之前没有减少 的引用计数. Perl 认为它有 2 个引用,但实际上只有 1 个,因此在解释器关闭之前它永远不会被垃圾回收。

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

于 2011-07-17T20:07:13.217 回答