refaddr 返回的值是永久的吗?
Is the value returned by refaddr permanent?
根据 Scalar::Util's documentation,refaddr
是这样工作的:
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.
但是,这并没有告诉我 $addr
是否是永久的。引用的 refaddr
会随时间变化吗?例如,在 C 中,运行 realloc
可以更改存储在动态内存中的某些内容的位置。这与 Perl 5 类似吗?
我问是因为我想制作一个 inside-out object,而且我想知道 refaddr($object)
是否会成为一把好钥匙。例如,在 XS 中编程时似乎最简单。
首先,不要重新发明轮子;使用 Class::InsideOut.
它是永久的。必须是,否则以下操作将失败:
my $x;
my $r = $x;
... Do something with $x ...
say $$r;
标量在固定位置有一个 "head"。如果 SV 需要升级(例如保存一个字符串),它是第二个内存块,称为 "body" 将发生变化。字符串缓冲区仍然是第三个内存块。
$ 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"[=12=] <-- 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"[=12=] <-- Changing the address of the string buffer
REFCNT = 2 doesn't change anything else.
CUR = 20
LEN = 22
根据 Scalar::Util's documentation,refaddr
是这样工作的:
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.
但是,这并没有告诉我 $addr
是否是永久的。引用的 refaddr
会随时间变化吗?例如,在 C 中,运行 realloc
可以更改存储在动态内存中的某些内容的位置。这与 Perl 5 类似吗?
我问是因为我想制作一个 inside-out object,而且我想知道 refaddr($object)
是否会成为一把好钥匙。例如,在 XS 中编程时似乎最简单。
首先,不要重新发明轮子;使用 Class::InsideOut.
它是永久的。必须是,否则以下操作将失败:
my $x;
my $r = $x;
... Do something with $x ...
say $$r;
标量在固定位置有一个 "head"。如果 SV 需要升级(例如保存一个字符串),它是第二个内存块,称为 "body" 将发生变化。字符串缓冲区仍然是第三个内存块。
$ 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"[=12=] <-- 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"[=12=] <-- Changing the address of the string buffer
REFCNT = 2 doesn't change anything else.
CUR = 20
LEN = 22