3

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.

Flimm
  • 136,138
  • 45
  • 251
  • 267
  • `$ref` is variable and thus subject to change, however it references to something (object?), and location of object should be permanent (as long it doesn't get recycled by going out of scope). – mpapec Feb 27 '15 at 11:03
  • 2
    [Class::InsideOut](http://search.cpan.org/perldoc?Class::InsideOut) – ikegami Feb 27 '15 at 13:51

1 Answers1

6

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;
... Do something with $x ...
say $$r;

Scalars have a "head" at a fixed location. If the SV needs an upgrade (e.g. to hold a string), it's 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

$ perl -MDevel::Peek -MScalar::Util=refaddr -E'
   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"x20;
   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
  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 address,
  FLAGS = (PADMY,POK,IsCOW,pPOK)                but head still at same address.
  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 address of the string buffer
  REFCNT = 2                                    doesn't change anything else.
  CUR = 20
  LEN = 22
ikegami
  • 367,544
  • 15
  • 269
  • 518