5

経営幹部レベルで参照を処理しようとすると、との違いを(実際には)理解できないようnewRV_incですnewRV_noincInline::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によって参照される配列のrefcountを取得できるとは思いません。)newRV_incarraynewRV_noincarrayref

perlgutsの例を読んだことがありますか:参照数と死亡率

AV* array = newAV()refcountが1の新しい配列を作成します。では、refcountが1の新しいSV(arrayref)を作成しながら、それを2make_arrayref_incにインクリメントします。これにより、関数を終了する前にrefcountをnewRV_incデクリメントしないため、メモリリークが発生します。array。Perlは参照が2つあると考えていますが、実際には1つしかないため、インタープリターがシャットダウンするまでガベージコレクションは行われません。

そのため、通常newRV_noinc、新しく作成された値への参照を返すコードで使用します。newRV_incを使用するよりも効率的ですSvREFCNT_decnewRV_noincAVの所有権をからに譲渡arrayすることと考えることができますarrayref

于 2011-07-17T20:07:13.217 に答える