2010-10-15 7 views
11

Quanto segue è una sessione di debug su Perl 5.12. Ha senso? UNIVERSAL memorizza nella cache una versione della variabile @ISA, che se per sempre utilizza più avanti. Indietro prima che lo Class::ISA fosse deprecato, ero solito chiamare Class::ISA::self_and_super_path per ottenere i componenti interni da ricollegare all'array @ISA. Dato che ora è considerato non necessario, come si fa a perl controllare i propri record interni?C'è un problema in perl 5.12.2 usando splice su @ISA?

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' 

Questo è il codice di prova (ovviamente). Sta ottenendo gli stessi risultati, eseguito a schermo piatto, eseguito come test o eseguito in debug. Devo dire che prima di questo @ISA = qw<Babushka> e ho eseguito

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

è che il problema? Dovresti sempre solo push su @ISA?

risposta

14

La sostituzione per Class::ISA::self_and_super_path è mro::get_linear_isa. È disponibile da mro o, se si desidera supportare vecchi perls, tramite MRO::Compat.

Inoltre, @ISA è una variabile magica.

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

Annotare la PERL_MAGIC_isa. Questo è ciò che guida questo particolare meccanismo.

Ogni volta che viene modificato, il contenuto di qualsiasi cache che si basa sul suo valore deve essere aggiornato.

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

pare aver trovato un caso in cui l'invalidazione della cache non avviene. Lo considero un bug. Le probabilità sono splice, per qualche motivo, non invoca la magia isa in modo appropriato. Si potrebbe provare a modificare @ISA in un modo alternativo, ad esempio utilizzando unshift o un compito, o eventualmente provare mro::method_changed_in, che invaliderebbe le cache di risoluzione dei metodi, che sono legate ai vari @ISA s.

Se fosse possibile ridurre questo bug a un testcase minimo, sarebbe estremamente utile per correggere questo bug.

Aggiornamento:

Una testcase minima si è rivelata facile:

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

Questo è causato da pp_splice non fare qualcosa di simile mg_set((SV *)ary). push, unshift e le assegnazioni regolari lo fanno correttamente, quindi l'utilizzo di uno di questi dovrebbe risolvere il problema.

Un altro aggiornamento:

This change, che ho appena impegnato a Perl, risolve il problema. Tuttavia, poiché il comportamento strano di splice non invocare la magia è già presente in 5.8 e 5.10, non è una regressione e quindi non entrerà a far parte di 5.12.3 in pochi mesi. 5.13.6, che sarà rilasciato la prossima settimana, e 5.14.0, la prossima primavera settentrionale, probabilmente lo avrà.

+0

Una patch per la vittoria! Grazie. – Axeman

+1

@Ether: http://rt.perl.org/rt3/Public/Bug/Display.html?id=78400 – Axeman

+0

Grazie per la patch rafl !! – Ether

4

Sì, c'è una cache. Ma se puoi modificare @ISA senza invalidare quella cache, lo considererei un bug in perl.

Il problema scompare se si aggiunge la linea @ISA = @ISA; dopo la linea splice?

+0

Proverà sicuramente '@ ISA = @ ISA'. Tranne che sarà più simile a '@ $ isa_ref = @ $ isa_ref'. Dove '$ isa_ref = * Papushka :: ISA {ARRAY}'. – Axeman

Problemi correlati