Понимание newRV_inc против newRV_noinc - PullRequest
5 голосов
/ 17 июля 2011

При попытке справиться со ссылками на уровне 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

Может кто-нибудь помочь мне понять, почему этот код ведет себя так?

1 Ответ

5 голосов
/ 18 июля 2011

Когда вы вызываете SvREFCNT($arrayref), вы получаете счетчик ссылок arrayref , а не array , на который он ссылается.newRV_inc увеличивает счетчик ссылок на array, а newRV_noinc - нет.Но это не имеет никакого значения для подсчета ссылок arrayref.(Я не думаю, что вы можете получить пересчет массива, на который ссылается arrayref с Devel :: Peek.)

Вы читали пример в perlguts: подсчет ссылок и смертность ?

AV* array = newAV() создает новый массив с refcount 1. 1. В make_arrayref_inc, newRV_inc увеличивает это значение до 2 при создании нового SV (arrayref) с refcount 1. Это вызываетутечка памяти, потому что вы не уменьшаете счет array перед выходом из функции.Perl считает, что у него есть 2 ссылки, но на самом деле он имеет только 1, поэтому он никогда не будет собирать мусор до тех пор, пока интерпретатор не отключится.

Вот почему вы обычно используете newRV_noinc в коде, который возвращает ссылку на недавносозданная ценность.Это более эффективно, чем использовать newRV_inc, а затем SvREFCNT_dec.Вы можете думать о newRV_noinc как о передаче права собственности на AV от array до arrayref.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...