在@ISA上使用拼接的perl 5.12.2中是否存在问题? [英] Is there a problem in perl 5.12.2 using splice on @ISA?

查看:63
本文介绍了在@ISA上使用拼接的perl 5.12.2中是否存在问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是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'

这是测试代码(显然).它获得相同的结果,平稳运行,作为测试运行或在调试中运行.我应该告诉你,在执行@ISA = qw<Babushka>之前,我执行了

splice( @ISA, 0, 0, 'Nanushka' );

是问题吗?您是否应该只将push放到@ISA上?

解决方案

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)

请注意PERL_MAGIC_isa.这就是驱动这种特殊机制的原因.

无论何时更改,都应该更新依赖于其值的所有缓存的内容.

$ perl -E'say Foo->isa(q[Bar]) || 0; @Foo::ISA = qw(Bar Baz); say Foo->isa(q[Bar]) || 0'
0
1

显然,您发现了一种情况,即不会发生缓存失效.我认为这是一个错误.出于某些原因,splice可能未正确调用isa魔术.您可以尝试以其他方式修改@ISA,例如使用unshift或分配,或者尝试使用mro::method_changed_in,这将使绑定到各种@ISA的方法解析缓存无效. /p>

如果您可以将此错误减少到最小的测试用例,那将对修复此错误有很大帮助.

更新:

事实证明,最简单的测试用例很简单:

$ perl -E'say Foo->isa(q[Bar]) || 0; splice @Foo::ISA, 0, 0, q[Bar]; say Foo->isa(q[Bar]) || 0'
0
0

这是由于pp_splice未执行类似mg_set((SV *)ary)的操作引起的. pushunshift和常规作业可以正确地做到这一点,因此使用其中一种应该可以解决您的问题.

另一个更新:

我刚致力于perl的

此更改修复了问题.但是,由于splice不调用魔术的奇怪行为已经在5.8和5.10中出现,因此它不是回归,因此在几个月内不会成为5.12.3的一部分.即将在下周发布的5.13.6和在明年春季的5.14.0将会发布.

The following is a debug session on Perl 5.12. Does this make any sense? Does UNIVERSAL cache a version of the @ISA variable, which if forever uses thereafer. Back before Class::ISA was deprecated, I used to call Class::ISA::self_and_super_path to get the internals to relook at the @ISA array. Since it is now considered unnecessary, how do you get perl to audit its internal records?

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'

This is test code (obviously). It's getting the same results, run flat, run as a test, or run in debug. I should tell you that prior to this @ISA = qw<Babushka> and I performed

splice( @ISA, 0, 0, 'Nanushka' );

Is that the problem? Should you only ever push onto @ISA?

解决方案

The replacement for Class::ISA::self_and_super_path is mro::get_linear_isa. That's available either from mro itself, or, if you want to support old perls, via MRO::Compat.

Also, @ISA is a magic variable.

$ 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)

Note the PERL_MAGIC_isa. That's what drives this particular mechanism.

Whenever it is changed, the contents of any caches that rely on its value are supposed to be updated.

$ perl -E'say Foo->isa(q[Bar]) || 0; @Foo::ISA = qw(Bar Baz); say Foo->isa(q[Bar]) || 0'
0
1

Apparently you've found a case where the cache invalidation doesn't happen. I consider this a bug. Chances are splice, for some reason, doesn't invoke the isa magic appropriately. You could try to modify @ISA in an alternative way, for example using unshift or an assignment, or possibly try mro::method_changed_in, which would invalidate the method resolution caches, which are bound to the various @ISAs.

If you could reduce this bug to a minimal testcase, that'd be hugely helpful in getting this bug fixed.

Update:

A minimal testcase turned out to be easy:

$ perl -E'say Foo->isa(q[Bar]) || 0; splice @Foo::ISA, 0, 0, q[Bar]; say Foo->isa(q[Bar]) || 0'
0
0

This is caused by pp_splice not doing something like mg_set((SV *)ary). push, unshift, and regular assignments do that correctly, so using one of these should fix your issue.

Another Update:

This change, which I just committed to perl, fixes the issue. However, as the odd behaviour of splice not invoking magic is already present in 5.8 and 5.10, it's not a regression and therefore not going to be part of 5.12.3 in a few months. 5.13.6, which will be released next week, and 5.14.0, next northern spring, will probably have it.

这篇关于在@ISA上使用拼接的perl 5.12.2中是否存在问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆