McDarren has asked for the wisdom of the Perl Monks concerning the following question:
However, this time I'm completely stumped.
Firstly, here is the offending code (for clarity, I removed some bits which are not relevant):
The above code is part of a bigger loop, that is iterating through a list of around 500 'hosts'. For each of these 'hosts', it will iterate through a list of 'tests', and for each one it checks to see if we have data for that test/host combination. If data is present, it gets used. Otherwise just a dash '-' is ouput (the else part of the loop).for my $test (@testlist) { if (defined $tref->{$host}{$test}) { my $status = $tref->{$host}{$test}{status}; my $duration = $tref->{$host}{$test}{dur}; # debugging line if (!$tref->{$host}{$test}{status}) { print "$host=>$test\n";} # Some more processing here which is not relevent } else { print "\t<th>-</th>\n"; } }
What I found was that just one single host/test combination (out of several thousand) was throwing the warning. With the print debugging line added, I narrowed it down to the 'http' test on the 'vnsgnnwwor-gw-1' host.
However - and this is the part that has me completely stumped - when I did a print Dumper($tref);1 immediately before this loop, the output for this particular host was:
So I've confirmed that the 'http' data for this host does not exist. So therefore my question is - how on earth is this getting past the conditional in the 'if' statement at the top of the loop? Am I being bitten by autovivification? If I am, then my understanding of how autovivification works is obviously way off. And if is is autovivification, then it doesn't make sense. Because there would be dozens and dozens of other test/host combinations that would also slip through - but only this single one is.'vnsgnnwwor-gw-1' => { 'conn' => { 'dur' => '2.09 hours', 'status' => 'red' }, 'mrtg' => { 'dur' => '4.00 hours', 'status' => 'green' } },
I can't help having the feeling that I'm missing something blatantly obvious here. Anyway, somebody please put me out of my misery.
Update: Okay, I have figured this one out, and I was being bitten by autovivification. Here is a self-contained example that demonstrates:
And the output of the above is:#!/usr/bin/perl -l use strict; use warnings; my $tref = { 'vnsgnnwwor-gw-1' => { 'conn' => { 'dur' => '2.09 hours', 'status' => 'red' }, 'mrtg' => { 'dur' => '4.00 hours', 'status' => 'green', }, }, }; my $host = 'vnsgnnwwor-gw-1'; my $test = 'http'; print "$host is ", defined $tref->{$host} ? "True" : "False"; print "$test is ", defined $tref->{$host}{$test} ? "True" : "False"; print "$test=>status is ", defined $tref->{$host}{$test}{status} ? "Tr +ue" : "False"; print "$test is ", defined $tref->{$host}{$test} ? "True" : "False";
Note that the first time I test for 'http', it returns false. But the second time that I test for it, it returns true. This is because (if my understanding of autovivification is correct), when I test for $tref->{$host}{$test}{status} - Perl obligingly creates the $test part of that datastructure for me - thanks to autovivification.vnsgnnwwor-gw-1 is True http is False http=>status is False http is True
I feel much better now :)
Thanks,
Darren :)
1. I use Data::Dumper::Simple for debugging
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Tracking down an uninitialized value warning
by quester (Vicar) on Jun 14, 2007 at 07:06 UTC | |
by McDarren (Abbot) on Jun 14, 2007 at 08:24 UTC | |
|
Re: Tracking down an uninitialized value warning
by sen (Hermit) on Jun 14, 2007 at 07:09 UTC | |
|
Re: Tracking down an uninitialized value warning
by GrandFather (Saint) on Jun 14, 2007 at 08:13 UTC | |
by McDarren (Abbot) on Jun 14, 2007 at 08:31 UTC |