According to Scalar::Util's documentation, refaddr works like this:
my $addr = refaddr( $ref );If $ref is reference the internal memory address of the referenced value is returned as a plain integer. Otherwise undef is returned.
However, this doesn't tell me if $addr is permanent. Could the refaddr of a reference change over time? In C, for example, running realloc could change the location of something stored in dynamic memory. Is this analogous for Perl 5?
I'm asking because I want to make an inside-out object, and I'm wondering whether refaddr($object) would make a good key. It seems simplest when programming in XS, for example.
First of all, don't reinvent the wheel; use Class::InsideOut.
It is permanent. It must be, or the following would fail:
my $x;
my $r = \$x;
$x = "abc"; # Do virtually anything with $x here.
say $$r;
Scalars have a head at a fixed location. If the SV needs an upgrade (e.g. to hold a string), it the address of a second memory block known as the body that will change. The string buffer is yet a third memory block.

use v5.14;
use Devel::Peek qw( Dump );
use Scalar::Util qw( refaddr );
my $x = 4;
my $r = \$x;
say sprintf "refaddr=0x%x", refaddr( $r ); Dump( $$r );
say "";
say "Upgrade SV:";
$x = 'abc';
say sprintf "refaddr=0x%x", refaddr( $r ); Dump( $$r );
say "";
say "Increase PV size:";
$x = "x" x 20;
say sprintf "refaddr=0x%x", refaddr( $r ); Dump( $$r );
refaddr=0x2e1db58
SV = IV(0x2e1db48) at 0x2e1db58 < SVt_IV variables can't hold strings.
REFCNT = 2 Head at 0x2e1db58; body at 0x2e1db48
FLAGS = (PADMY,IOK,pIOK)
IV = 4
Upgrade SV:
refaddr=0x2e1db58
SV = PVIV(0x2e18b40) at 0x2e1db58 < Scalar upgrade to SVt_PVIV.
REFCNT = 2 New body at new addr (0x2e18b40), but
FLAGS = (PADMY,POK,IsCOW,pPOK) head still at same addr (0x2e1db58)
IV = 4
PV = 0x2e86f20 "abc"\0 < The scalar now has a string buffer.
CUR = 3
LEN = 10
COW_REFCNT = 1
Increase PV size:
refaddr=0x2e1db58
SV = PVIV(0x2e18b40) at 0x2e1db58
REFCNT = 2
FLAGS = (PADMY,POK,pPOK)
IV = 4
PV = 0x2e5d7b0 "xxxxxxxxxxxxxxxxxxxx"\0 < Changing the addr of the string buf
REFCNT = 2 doesn't change anything else.
CUR = 20
LEN = 22
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