I'm posting this because it's a demonstration of an interesting feature in Perl that can cause strange bugs. I worked and worked at finding out what was wrong with the following snippet. It's a subtle bug and I'm not too embarrassed at missing it. It's a mistake I hopefully won't repeat. Can you find it? If you find it too quickly, don't spoil it for the others, though :)
while ( my $data = $t_sth->fetchrow_arrayref ) { my ( $amt, $id ) = @$data; $amt /= PRECISION; SWITCH: { $id == $CASH && ($tcash += $amt) && last SWITCH; $id == $ACCOUNT && ($taccount += $amt) && last SWITCH; $id == $CHECK && ($tcheck += $amt) && last SWITCH; $id == $GIFT && ($tgift += $amt) && last SWITCH; $id == $VOUCHER && ($tvoucher += $amt) && last SWITCH; $id == $CC_MAN_AUTH && ($tcc_man_auth += $amt) && last SWITCH; ($tcredit += $amt); } }
Hint: the bug is in the switch statement. All data entering the switch statement is correct. Further, $id and the values it compares with are both integers (i.e., no floating point comparisons).
chromatic was shown this and he rewrote it with this. Bonus points if you see how it works.
my %totals; @totals{$CASH, $ACCOUNT, $CHECK, $GIFT, $VOUCHER, $CC_MAN_AUTH} = \($tcash, $taccount, $tcheck, $tgift, $tvoucher, $tcc_man_auth); while ( my $data = $t_sth->fetchrow_arrayref ) { my ( $amt, $id ) = @$data; $amt /= PRECISION; if (my $totalvar = $totals{ $id }) { $$totalvar += $amt; } else { $tcredit += $amt; } }
His is a better solution than mine in that it works, but discovering that taking a reference is a distributive action (the assignment to the hash slice) was surprising! He assures me that this is a documented feature.
Update: Congrats to dws for being the first person to accurately identify and describe the bug.
Cheers,
Ovid
Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Pop quiz: find the bug
by VSarkiss (Monsignor) on Jul 03, 2002 at 23:19 UTC | |
by Aristotle (Chancellor) on Jul 03, 2002 at 23:37 UTC | |
Re: Pop quiz: find the bug
by dws (Chancellor) on Jul 03, 2002 at 23:13 UTC | |
Re: Pop quiz: find the bug
by Anonymous Monk on Jul 03, 2002 at 23:20 UTC | |
by blakem (Monsignor) on Jul 03, 2002 at 23:33 UTC | |
Re: Pop quiz: find the bug
by Aristotle (Chancellor) on Jul 03, 2002 at 23:23 UTC | |
by FoxtrotUniform (Prior) on Jul 04, 2002 at 02:28 UTC | |
Re: Pop quiz: find the bug
by Zaxo (Archbishop) on Jul 03, 2002 at 23:24 UTC | |
Re: Pop quiz: find the bug
by jjohn (Beadle) on Jul 04, 2002 at 14:06 UTC | |
by Abigail-II (Bishop) on Jul 04, 2002 at 14:34 UTC | |
by jjohn (Beadle) on Jul 05, 2002 at 05:59 UTC | |
by Abigail-II (Bishop) on Jul 05, 2002 at 09:36 UTC | |
by chromatic (Archbishop) on Jul 04, 2002 at 16:54 UTC | |
by jjohn (Beadle) on Jul 05, 2002 at 05:42 UTC | |
Re: Pop quiz: find the bug
by Anonymous Monk on Jul 04, 2002 at 03:01 UTC |