"Valoare neinitializată" fals pozitivă

Cred că PERL (5.8.8 pe nucleul CentOS 2.6.18-308.8.1.el5) îmi dă o avertizare falsă "variabilă neinitializată". Toate căutările mele se transformă în probleme legitime de valoare neinitializată. Poate că și al meu este prea, și dacă este cazul, atunci o explicație a ceea ce se întâmplă (și cum să faceți corect ceea ce încerc să fac) ar fi minunat. Am analizat, de asemenea, multe referințe pentru hex() și idiomele argumentului corect al funcției, și cred că fac toate acestea în mod corect.

Scriptul meu citește 2 fișiere text: unul conține adresa de hardware pe 32 de biți, iar celălalt conține date citite din acea adresă de 32 de biți. Valorile din fiecare fișier sunt întotdeauna 8 cifre hexa lungime și ambele fișiere sunt 100% potrivite (linia 1 din fișierul Adresă corespunde cu linia 1 din fișierul de date). Când valoarea datelor nu este zero, totul este bine, dar când valoarea datelor este de 0, primesc avertismentul:

Use of uninitialized value in string eq at ../VMetro_Parser.pl line 248.
Use of uninitialized value in hex at ../VMetro_Parser.pl line 250.

Codul relevant:

sub ppReg_TX_Mode_Reg {
    my( $data ) = @_; # first arg should be the Data field
    my $ret = "\t";
    if( $data eq "00000000" ) { print "TX_Mode_Reg got 0 input\n"; } #LINE 248
    #croak( "data not defined!" ) unless defined $data;
    my( $hex ) = hex($data); #LINE 250

    $ret .= sprintf( "Clear INTs: %02X   ",         (($hex >> 25) & 0x7F) );

Intrare care produce comportamentul așteptat:

Address: 90000004
Data: 00000004

Rezultatul scriptului PERL:

90000004 00000004 ->  Wr TX00 Mode_Reg
    Clear INTs: 00

Intrare care produce avertizarea "neinitializată" neașteptată:

Address: 90000004
Data: 00000000

Rezultatul scriptului PERL:

90000004 00000000 ->  Wr TX00 Mode_Reg
TX_Mode_Reg got 0 input
    Clear INTs: 00

În mod evident, recunoaște un argument transmis ca șirul "00000000" și totuși, de asemenea, crede că este undef (linia croak se declanșează dacă l-am decomentat). Ce dă?

Un lucru interesant este că există și alte exemple de date fiind 0, dar nu sunt aruncate avertismente. Aceste alte date 0 sunt prelucrate de o altă funcție și apar după linia care aruncă avertizarea, dar procesarea este identică (cu excepția acțiunilor evidente de depanare din codul de mai sus, care au fost adăugate numai din cauza avertismentului).

DE EXEMPLU.

sub ppReg_RX_Master_Mode_Reg {
    my( $data ) = @_; # first arg should be the Data field
    my $ret = "\t";
    my( $hex ) = hex($data);

Nu arunca avertismente.

0
Ne pare rău despre separarea avertismentelor de ieșire. Am redirecționat ieșirea într-un fișier, așa că l-aș putea copia/lipi aici și nu l-am recombinat corect. Mi-am dat seama de problema mea si voi posta un Raspuns de mai jos, dar am vrut sa mentionez ca Data :: Dumper a ajutat intr-adevar la ceea ce se intampla. Am avut probleme cu importul Devel :: Peek, așa că nu am încercat niciodată asta. Dacă îmi dau seama cum să votez un comentariu, o să fac asta pentru tine.
adăugat autor Tim, sursa
Nu putem spune din ce ați postat ce argument a primit ppReg_TX_Mode_Reg . Puteți reproduce acest lucru cu un scenariu mai mic? Vă rugăm să postați un exemplu complet.
adăugat autor Gilles, sursa
Ar trebui să verificați intrarea cu Data :: Dumper . Este o modalitate foarte bună de a depana script-uri, precum și un modul de bază. print Dumper $ data </​​code> vă va anunța exact ce este în variabila dumneavoastră. De asemenea, în întrebarea dvs. nu există suficiente informații pentru a face altceva decât pentru a ghici, așadar vă recomand să creați un exemplu autonom, dacă este posibil.
adăugat autor TLP, sursa
Nu există avertismente în ceea ce pretindeți că este produsul?!?!
adăugat autor ikegami, sursa
Numele limbii este "Perl". Nu este un acronim.
adăugat autor ikegami, sursa
utilizați Devel :: Peek qw (Dump); Dump ($ data); (înainte de comparare) ar putea fi instructiv.
adăugat autor ikegami, sursa
@TLP, Data :: Dumper nu vă anunță "exact ce este în variabila dvs.". Asta i-am propus lui Devel :: Peek. Dacă acesta este un bug în Perl, detaliile suplimentare ar conta.
adăugat autor ikegami, sursa

2 răspunsuri

As expected, the problem was with my code and not Perl :) I am using a Dispatch Table to call my processing functions. A typo in the Dispatch Table definition caused the function to be called when Perl was processing the declaration of the table.

Cod incorect:

# 'Dispatch table' is a hash for functions
my %regPPFn = (
        TX_Version_Reg  =>  \&ppReg_TX_Version_Reg,
        TX_Mode_Reg =>  \&ppReg_TX_Mode_Reg,
        TX_Run_Reg  =>  \&ppReg_TX_Run_Reg,
        ...
        # Note: GCs are mostly TXs, so mostly call the TX fn()s
        GC_Version_Reg  =>  \&ppReg_TX_Version_Reg,
        GC_Mode_Reg =>  &ppReg_TX_Mode_Reg,
        GC_DMA =>   \&ppReg_GC_DMA,
        GC__Reg =>  \&ppReg_GC__Reg,
        "" => sub { print "Dispatch table NULL lookup\n" }
        ); # Array of pointers to register Pretty Print functions

Puteți vedea că referința funcției pentru * GC_Mode_Reg * nu are backslash înainte de ampersand.

GC_Mode_Reg =>  &ppReg_TX_Mode_Reg,

ar trebui să fie

GC_Mode_Reg =>  \&ppReg_TX_Mode_Reg,

Folosind Data :: Dumper-ul a fost un prim pas mare pentru a ma obtine pe drumul cel bun si mi-a aratat ca functia mea a fost chemata o data inainte ca aceasta "sa fie posibil sa fie numita". Utilizând $ | = 1, de asemenea, m-au ajutat să cred comanda textul de ieșire; Mă gândeam că mesajele de avertizare care au ieșit înainte de declarațiile mele de tipar s-au datorat tamponării.

Since the solution was a good deal away from the initial hypothesis/question title, let me know if & how you think I should edit this question. I hesitate to change it much since someone else with the same problem will probably be looking in the wrong place the same as I was.

0
adăugat

Este foarte puțin probabil să fie o problemă cu Perl.

Amintiți-vă că avertismentele sunt trimise la STDERR, în timp ce ieșirea dvs. va fi STDOUT. Cele două nu sunt neapărat sincronizate, astfel încât să nu puteți lega avertismentul cu ieșirea pentru aceeași înregistrare.

Aceasta poate ajuta la utilizarea print și die în loc de croak , astfel încât avertismentele să fie afișate în ordinea corectă.

Vă sugerez să vă schimbați subrutina

sub ppReg_TX_Mode_Reg {
  my ($data) = @_;
  do { warn 'Undefined $data parameter'; return; } unless defined $data;

  . . .
}

astfel încât codul să nu fie executat pentru date nevalide.

Problema dvs. este probabil să fie în codul care extrage datele din înregistrările fișierelor. Manipulați corect liniile goale? Arătați această parte a codului dacă doriți ajutor.

0
adăugat
Adăugând $ | = 1; (pentru a dezactiva tamponarea pe STDOUT) ar putea ajuta și cu astfel de probleme.
adăugat autor ikegami, sursa