Понимание newRV_inc против newRV_noinc
При попытке справиться со ссылками на уровне 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_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
Может кто-нибудь помочь мне понять, почему это ведет себя так?
1 ответ
Когда вы звоните SvREFCNT($arrayref)
вы получаете счетчик ссылок на arrayref, а не массив, на который он ссылается. newRV_inc
увеличивает счетчик ссылок array
, а также newRV_noinc
не делает. Но это не имеет никакого значения для подсчета ссылок arrayref
, (Я не думаю, что вы можете получить на refcount массив, на который ссылается arrayref с Devel::Peek.)
Вы читали пример в perlguts: подсчет ссылок и смертность?
AV* array = newAV()
создает новый массив с рефконтом 1. В make_arrayref_inc
, newRV_inc
увеличивает это значение до 2 при создании нового SV (arrayref) с refcount 1. Это вызывает утечку памяти, потому что вы не уменьшаете array
Пересчет перед выходом из функции. Perl считает, что у него есть 2 ссылки, но на самом деле есть только 1, поэтому он никогда не будет собирать мусор, пока интерпретатор не отключится.
Вот почему вы обычно используете newRV_noinc
в коде, который возвращает ссылку на вновь созданное значение. Это более эффективно, чем использование newRV_inc
а потом SvREFCNT_dec
, Вы можете думать о newRV_noinc
как передача права собственности на АВ от array
в arrayref
,