Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

undefined value in array reference

by Dandello (Scribe)
on Mar 31, 2011 at 17:49 UTC ( #896676=perlquestion: print w/replies, xml ) Need Help??
Dandello has asked for the wisdom of the Perl Monks concerning the following question:


sub popnum3 { my ( $x, $y, $z ) = @_; my @row = @{$aob[ $y - 1 ]}; my $mean = mean(@row); $aob[$x][$y] = $mean * ( 1 + $z ); return $aob[$x][$y]; }

This subroutine is failing randomly - it will (apparently) run properly for 500+ lines then throw an 'undefined value in ARRAY reference'. The line referred to in the error message is my @row  = @{$aob[ $y - 1 ]};

Now, $x is a column reference, $y is a row reference, $z is a pre-defined random number. @aob is a 2-d array that is also printed to a file since it has to be accessed later by a different script - I can look at that file and know that row $y-1 is fully populated. Running diagnostics also tells me that $x, $y and $z all have appropriate numeric values. When the subroutine does throw this error - $x is always 0.

Obviously I'm missing something in regards to turning row $y-1 of array @aod into @row, so pointing me in the right direction is appreciated.

Replies are listed 'Best First'.
Re: undefined value in array reference
by kennethk (Abbot) on Mar 31, 2011 at 18:02 UTC
    The most likely situation is that you are trying to dereference a row before it is initialized: demonstrated by the code:

    #!/usr/bin/perl use strict; use warnings; my @row = ( [1] ) x 3; print @{$row[2]}, "\n"; print @{$row[3]}, "\n";
    Are you sure @aob contains what you think it does? See How can I visualize my complex data structure?. You can also wrap your dereference in an eval to catch the case where it fails, like:

    sub popnum3 { use Data::Dumper; my ( $x, $y, $z ) = @_; my @row = eval{@{$aob[ $y - 1 ]}} or die "$x\n$y\n$z\n", Dumper $ +aob[ $y - 1 ]; my $mean = mean(@row); $aob[$x][$y] = $mean * ( 1 + $z ); return $aob[$x][$y]; }

      Maybe add some parameter validation to your subroutine to catch out of bound errors?

      sub popnum3 { my ( $x, $y, $z ) = @_; warn "y=$y is out of bounds" if $y - 1 > $#aob || ! ref $aob[ $y - + 1 ]; my @row = @{$aob[ $y - 1 ]}; my $mean = mean(@row); $aob[$x][$y] = $mean * ( 1 + $z ); return $aob[$x][$y]; }

      Update: Meant to be reply to OP

      Okay, using KennethK's snippet above gives : uncaught exception from user code; snip ('4\x{a}501\x{a}\0\x{a}', '$VAR1 = undef;\x{a}')

      Now the row I'm trying to get has already been printed into the data file. But running through every row in the file seems a little memory consuming when the same data should be in the array.

      What seems to be happening is is  @{$aob[ $y - 1 ]} just isn't getting me the row from the array.

      In a different subroutine I have $aob[$x][ $y - 1 ] and there are always values there and it works properly - it's getting that entire row ($y - 1) into a separate array so I can get the mean of the row that's giving me problems.

      The code for getting the row comes from Dennis's Quick Guide and I haven't found that particular algorithm anywhere else.

      It would be nice to get the row algorithm to work as a one-liner. But it would be even nicer to just get it to work.

        At the time of the dereference, the $y-th value of @aob is empty. It's certainly possible for the $y-th value to be empty when the $x-th value is not - $x just has to be less than $y. Perhaps you really mean my @row  = @{$aob[ $x ]};? This sounds very much like an indexing error. A readthrough of perlreftut/perldsc might be helpful.

        Otherwise, I'll need to see your issue in broader context - a complete script with sample input and intended/desired output, all wrapped in <code> tags would be ideal.

Re: undefined value in array reference
by davido (Archbishop) on Mar 31, 2011 at 18:53 UTC

    In your writeup you mention @aod, and in the script show us @aob. @aob is never declared within the sub popnum3. A first step toward keeping things from breaking easily is to make sure that all the variables used in a sub are passed to it explicitly, rather than absorbing from outer scopes. Perhaps you could pass @aob from an outer scope like this:

    sub popnum3 { my @inner_aob = @{ shift @_ }; # reconstitute a reference


    sub popnum3 { my $aobref = shift @_; # Just pass and use the ref instead.

    As soon as subs start absorbing values rather than having values passed to them, they become fragile, and it makes it all the harder to track down the effects of small changes elsewhere in the code. Keeping scopes narrow and passing values reduces 'errors at a distance.' This isn't actually the specific error you're describing, but it as advice that will make your code easier to deal with.


      @aod was a typo. Sorry

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://896676]
Approved by kennethk
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2017-09-23 09:48 GMT
Find Nodes?
    Voting Booth?
    During the recent solar eclipse, I:

    Results (272 votes). Check out past polls.