Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the value returned by refaddr permanent?

Tags:

perl

perlguts

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.

like image 691
Flimm Avatar asked Oct 22 '25 21:10

Flimm


1 Answers

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.

Layout of an SVt_PVIV scalar

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
like image 73
ikegami Avatar answered Oct 25 '25 13:10

ikegami



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!