【问题标题】:Is the value returned by refaddr permanent?refaddr 返回的值是永久的吗?
【发布时间】:2015-02-27 10:47:24
【问题描述】:

根据Scalar::Util's documentationrefaddr 是这样工作的:

my $addr = refaddr( $ref );

如果 $ref 是引用,则引用值的内部内存地址作为纯整数返回。否则返回undef。

但是,这并不能告诉我$addr 是否是永久的。参考的refaddr 会随着时间而改变吗?例如,在 C 中,运行 realloc 可以更改存储在动态内存中的内容的位置。这与 Perl 5 类似吗?

我问是因为我想制作一个inside-out object,我想知道refaddr($object) 是否会成为一把好钥匙。例如,在 XS 中编程时似乎最简单。

【问题讨论】:

  • $ref 是可变的,因此可能会发生变化,但是它引用了某些东西(对象?),并且对象的位置应该是永久性的(只要它不会因超出范围而被回收)。

标签: perl perlguts


【解决方案1】:

首先,不要重新发明轮子;使用Class::InsideOut


它是永久的。必须是,否则以下操作将失败:

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

标量在固定位置有一个“头”。如果 SV 需要升级(例如,保存一个字符串),它是一个称为“主体”的第二个内存块,它将发生变化。字符串缓冲区是第三个内存块。

$ 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

【讨论】:

    猜你喜欢
    • 2012-08-26
    • 1970-01-01
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多