Является ли значение, возвращаемое refaddr постоянным?

Согласно документации Scalar:: Util, refaddr работает так:

my $addr = refaddr( $ref );

Если $ref является ссылкой, адрес внутренней памяти указанного значения возвращается в виде простого целого числа. В противном случае undef возвращается.

Тем не менее, это не говорит мне, если $addr является постоянным Может ли refaddr изменения ссылки с течением времени? В C, например, работает realloc может изменить местоположение чего-то, хранящегося в динамической памяти. Является ли это аналогом для Perl 5?

Я спрашиваю, потому что я хочу сделать объект наизнанку, и мне интересно, refaddr($object) сделал бы хороший ключ. Это кажется самым простым при программировании в XS, например.

1 ответ

Решение

Прежде всего, не изобретайте велосипед; используйте Class:: InsideOut.


Это навсегда. Должно быть, иначе не получится:

my $x;
my $r = \$x;
... Do something with $x ...
say $$r;

Скаляры имеют "голову" в фиксированном месте. Если SV нуждается в обновлении (например, для хранения строки), это будет второй блок памяти, известный как "тело", которое изменится. Строковый буфер - это еще третий блок памяти.

Схема скаляра SVt_PVIV

$ 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
Другие вопросы по тегам