Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Error ... at (eval 75) line 7974.

by syphilis (Archbishop)
on Apr 13, 2009 at 09:36 UTC ( [id://757187]=perlquestion: print w/replies, xml ) Need Help??

syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
The actual error message is:
Can't use an undefined value as an ARRAY reference at (eval 75) line 7 +974.
I know what it means, but I've never got my head around working out how to determine the precise line of code that's producing the error (when messages of this type are thrown up).
Any advice on how to track down the line of code that's generating the error would be appreciated.

That's the only output I'm getting when running this particular script - it's a test script for a module that I'm developing.

Cheers,
Rob

Replies are listed 'Best First'.
Re: Error ... at (eval 75) line 7974.
by ELISHEVA (Prior) on Apr 13, 2009 at 10:54 UTC
    The main problem is finding the particular call to the string eval that is causing the problem. What I do for these situations is:
    • use grep (or your code editors search facility) to find all of the calls to eval
    • insert print STDERR "before eval: <$sEval>\n" Although in this case you might want to print out only a substring rather than the whole string for evaluation.
    • If you don't mind a being a bit wordier, instead of the above, you can insert the following instead print STDERR "before eval \@ line " . __LINE__ . " of file " . __FILE__ . ": <$sEval>\n"
    • insert print STDERR "after eval\n"; after each eval.
    • Watch what happens

    That should at least help you isolate the particular eval that is causing the problem. However, your real issue is a 7000 line file being eval'd at once. Once you know what string is being eval'd, I would recommend that you put the code in a file and test it running as a normally compiled script.

    7000+ lines is awfully long for any script or module, even a test script. I usually try to keep them under 1000 lines and no more than 3000 in really unusual circumstances. You might want to think about how you can trim that down by

    • moving repetitive code into subroutines
    • data into support files
    • splitting up the code into separate more focused modules (i.e. test framework modules)

    Best, beth

      The main problem is finding the particular call to the string eval that is causing the problem

      If you run the script under the debugger (perl -d), it'll give the location of the relevant eval in the error message; locating the offending dereference is then just a matter of arithmetic.

      It feels like there should be an even more convenient way to do this -- some combination of command-line options that would produce the more informative error message without going through the interactive debugger -- but I personally don't know of one.

        It feels like there should be an even more convenient way to do this

        Too bloody right it does ... so far it seems that "at (eval 75) line 7974" is, in effect, just another way of saying "somewhere or other".

        There is no string eval in the script itself, or in the modules it directly loads - though there could be a string eval in one of the modules that ultimately gets loaded. (I'm looking at you, Parse::RecDescent.)

        I have established that the problem goes away if I replace Parse-RecDescent-1.96.0 with Parse-RecDescent-1.94. I get the feeling that it's just a matter of explicitly assigning [] to a hashref key if that key is undef ... in which case it's just a matter of working out which key it is. Maybe it's time to try a time a dump of the hash reference.

        Btw, I don't doubt that my problem would be made simpler if I was debugger-savvy, or Carp-savvy (as bloodnok and Anonymous Monk suggested).

        I did have a bit of a play with Carp, but only got a heap of Parse::RecDescent messages that didn't mean much.

        Cheers,
        Rob
Re: Error ... at (eval 75) line 7974.
by Fletch (Bishop) on Apr 13, 2009 at 13:42 UTC

    You might try explicitly setting a more meaningful line number and name via the #line directive (similar to what many incarnations of cpp grok):

    my $line = 99; for my $n ( qw/foo bar baz/ ) { my $code = <<"EOT"; #line $line "$n" die "aieee!" EOT eval $code; if( $@ ) { print "Died: $@\n"; } } __END__ Died: aieee! at foo line 99. Died: aieee! at bar line 99. Died: aieee! at baz line 99.

    See Plain Old Comments (Not!) in perlsyn for more details.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      You might try explicitly setting a more meaningful line number

      Well ... yes, I might have to try and do something like that, though at this stage I've no idea where that line number needs to be set. But then, I haven't even yet made a serious attempt to find the string eval responsible. I do know that the error occurs after (in Inline/C.pm) $parser->code($o->{ILSM}{code}) gets called and before it returns. ($parser is a Parse::RecDescent object, and code() is a Parse::RecDescent method.)

      The problem occurs only with Inline::CPP and Parse::RecDescent versions later than 1.94 (no problem with Inline::C), and has already been reported for Parse-RecDescent-1.95 at http://rt.cpan.org/Public/Bug/Display.html?id=33366. Obviously, the issue has not been addressed in 1.96, though it could be an Inline::CPP bug faik.

      For the time being I can live with the fact that Parse-RecDescent-1.94 (or perhaps earlier) is specifically needed. No doubt I'll continue to investigate as time and energy permit.

      Many thanks for the replies.

      Cheers,
      Rob

        Have you tried enabling trace? our $::RD_TRACE = 1;

        If that output doesn't help you track back to the C/C++ code that's being mis-parsed, then you could try my old standby:

        perl -d:Trace yourICscript.pl 2>trace

        You'll want to ensure you have plenty of free diskspace and something else to do for a few hours--sleeping's good. Cos a program that would run for a few seconds normally, can take hours. But generally, especially if you can make the error fatal (maybe Fatal?), then when it stops the last couple of hundred lines of the trace tell you everything you need to know.

        If you want to get sophisticated, you can turn the tracing off at the top of your program and then turn it on just before whatever line of your code instigated the code that issues the warning. It can get you there more quickly. Good luck.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        For others who may have run into this and subsequently destroyed their brain like the rest of us, I believe the exact change in RecDescent that is causing issues is this:

        (from the Changes file)

        1.90 Tue Mar 25 01:17:38 2003 - BACKWARDS INCOMPATIBLE CHANGE: The key of an %item entry for a repeated subrule now includes the repetition specifier. For example, in: sentence: subject verb word(s) the various matched items will be stored in $item{'subject'} +, $item{'verb'}, and $item{'word(s)'} (i.e. *not* in $item{'wo +rd'}, as it would have been in previous versions of the module). (thanks Anthony)

        In my case, I had something like this:

        Item(s) EOF { $return = [ @{$item{Item}} ]; }
        and it *should be*:
        Item(s) EOF { $return = [ @{$item{qq(Item(s))}} ]; }

        Check other sub-rules for similar kind of behavior and hash referencing.

        It's also actually already documented within the grammer included by Inline::CPP:

        http://cpansearch.perl.org/src/SHASSAN/Inline-CPP-0.27/grammar/grammar.pm

        Unfortunately to figure it out myself, I had to take the long road on an entirely different piece of older code. Just the type of thing to make one tear their hair out unless they know the exact place to look.

Re: Error ... at (eval 75) line 7974.
by Bloodnok (Vicar) on Apr 13, 2009 at 10:00 UTC
    use Carp; ... confess(); invariably works for me ... AFAIR, diagnostics can be of not inconsiderable help as well (from a stack trace POV) - tho' it's a while since I last used it...

    A user level that continues to overstate my experience :-))
Re: Error ... at (eval 75) line 7974.
by Anonymous Monk on Apr 13, 2009 at 10:05 UTC
    Look for line 7974 of string eval (eval "").
    $ cat eval.line.pl #!/usr/bin/perl use strict; use warnings; for( 1 .. 2){ eval q{ my $foo = (undef)->[1]; die "Oh noes!!"; }; warn $@; warn "EEEK"; } warn "Arggg!!!"; $ perl eval.line.pl Can't use an undefined value as an ARRAY reference at (eval 1) line 2. EEEK at eval.line.pl line 14. Can't use an undefined value as an ARRAY reference at (eval 2) line 2. EEEK at eval.line.pl line 14. Arggg!!! at eval.line.pl line 16. $
    Consider using Carp
Re: Error ... at (eval 75) line 7974.
by deepsoul (Initiate) on Oct 10, 2011 at 18:52 UTC
    I hit on this old thread when I had the same problem, and later found out something not previously mentioned. Setting
    $^P= 0x100;
    gives you the source line of the eval itself in addition to the line within the eval:
    Use of uninitialized value in print at (eval 1)[./testeval.pl:12] li +ne 1.
    I found this quite useful for tracking down the offending eval'ed code. See the documentation of $^P / $PERLDB in perlvar for details.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://757187]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (6)
As of 2024-04-19 11:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found