Axe*_*man 11 oop perl universal
以下是Perl 5.12上的调试会话.这有意义吗?是否UNIVERSAL缓存版本的@ISA变量,如果永远采用随后上.回到之前Class::ISA不推荐使用,我曾经打电话Class::ISA::self_and_super_path让内部人员重新看一下@ISA阵列.既然现在认为没必要,你如何让perl审核其内部记录?
DB<34> p $papa
Papushka=HASH(0x16bc0300)
DB<35> p $papa->isa('Nanushka')
DB<36> p $papa->isa('Babushka')
1
DB<37> x @Papushka::ISA
0 'Nanushka'
1 'Babushka'
Run Code Online (Sandbox Code Playgroud)
这是测试代码(显然).它获得相同的结果,运行平稳,作为测试运行或在调试中运行.我应该告诉你,在此之前@ISA = qw<Babushka>,我表演了
splice( @ISA, 0, 0, 'Nanushka' );
Run Code Online (Sandbox Code Playgroud)
那是问题吗?如果你永远只能push到@ISA?
raf*_*afl 14
替换Class::ISA::self_and_super_path是mro::get_linear_isa.这可以从mro它自己,或者,如果你想支持旧的perls,通过MRO::Compat.
另外,@ISA是一个神奇的变量.
$ perl -MDevel::Peek -e'Dump \@ISA'
SV = IV(0x1b92e20) at 0x1b92e28
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x1bbcd58
SV = PVAV(0x1b93cf8) at 0x1bbcd58
REFCNT = 2
FLAGS = (SMG,RMG)
MAGIC = 0x1bc0f68
MG_VIRTUAL = &PL_vtbl_isa
MG_TYPE = PERL_MAGIC_isa(I)
MG_OBJ = 0x1bbcd40
ARRAY = 0x0
FILL = -1
MAX = -1
ARYLEN = 0x0
FLAGS = (REAL)
Run Code Online (Sandbox Code Playgroud)
请注意PERL_MAGIC_isa.这就是驱动这种特殊机制的原因.
每当它被更改时,应该更新依赖于其值的任何缓存的内容.
$ perl -E'say Foo->isa(q[Bar]) || 0; @Foo::ISA = qw(Bar Baz); say Foo->isa(q[Bar]) || 0'
0
1
Run Code Online (Sandbox Code Playgroud)
显然你发现了一个不会发生缓存失效的情况.我认为这是一个错误.splice由于某种原因,机会不会isa适当地调用魔法.您可以尝试以@ISA另一种方式进行修改,例如使用unshift或赋值,或者可能尝试mro::method_changed_in,这将使方法解析缓存无效,这些缓存绑定到各种@ISAs.
如果你可以将这个bug减少到一个最小的测试用例,这对于修复这个bug非常有帮助.
更新:
最小的测试用例变得简单:
$ perl -E'say Foo->isa(q[Bar]) || 0; splice @Foo::ISA, 0, 0, q[Bar]; say Foo->isa(q[Bar]) || 0'
0
0
Run Code Online (Sandbox Code Playgroud)
这是因为pp_splice没有做类似的事情mg_set((SV *)ary).push,unshift和常规分配正确地执行,因此使用其中一个应该可以解决您的问题.
另一个更新:
我刚刚致力于perl的这一变化解决了这个问题.然而,由于splice5.8和5.10中已经存在不调用魔法的奇怪行为,因此它不是回归,因此在几个月内不会成为5.12.3的一部分.将于下周发布的5.13.6和下一个北方春季的5.14.0可能会有它.