In trying to deal with references at the C level I can't seem to figure out the difference (in practice) between newRV_inc
and newRV_noinc
. To that end I have mocked up this little Inline::C
example.
#!/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
gives:
inc: 1
noinc: 1
Can anyone help me understand why this code behaves this way?
When you call SvREFCNT($arrayref)
you're getting the reference count of the arrayref, not the array that it's referencing. newRV_inc
increments the reference count of array
, and newRV_noinc
doesn't. But that doesn't make any difference to the reference count of arrayref
. (I don't think you can get at the refcount of the array referenced by an arrayref with Devel::Peek.)
Have you read the example in perlguts: Reference Counts and Mortality?
AV* array = newAV()
creates a new array with a refcount of 1. In make_arrayref_inc
, newRV_inc
increments that to 2 while creating a new SV (the arrayref) with a refcount of 1. This causes a memory leak, because you don't decrement array
's refcount before exiting the function. Perl thinks it has 2 references, but it really only has 1, so it will never be garbage collected until the interpreter shuts down.
That's why you normally use newRV_noinc
in code that returns a reference to a newly created value. It's more efficient than using newRV_inc
and then SvREFCNT_dec
. You can think of newRV_noinc
as transferring ownership of the AV from array
to arrayref
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With