Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

This meditation is a story about how the aliasing semantics of perl has caused me a hard-to-find bug. This is not meant to prove that aliasing is useless, I know how useful it can be in other circumstances.

Suppose I have an array of intermediate results (the numbers below are for illustration only):

my @root = (1022, 2);
While debugging a program, I decided to dump the array at one point of the program. However, I thought that the array could get too large, so I decided to print only the first eight elements. I knew that all the elements of the array were defined, so I decided to do this:
$verbose and warn "found " . @root . " root nodes: " . join(" ", grep +{ defined } @root[0 .. 7]);
Unexpectedly, this caused a different error in the program, resulting in these messages:
Use of uninitialized value in hash element at ./rock-cut line 163. Can't use an undefined value as an ARRAY reference at ./rock-cut line +171.
It took me quite a lot of time to figure out what was wrong. The program wasn't running very fast, so I had to wait for its completion after each change. I didn't try to run it with DB, because that would make the program about 4 times slower.

After a while, I figured out that if I change the line to this, the bug disappears:

$verbose and warn "found " . @root . " root nodes: " . join(" ", @root +[0 .. (@root < 8 ? @root : 8) - 1]);

I was very surprised, because I wouldn't have thought this change could make any difference. But the fact is that the first version has changed the array.

Recall that @root had two elements. This expression

grep { defined } @root[0 .. 7]
has made the elements @root[2 .. 7] spring into existsance, thus the array has grown to 8 long. This has caused a problem later, when I iterated through @root and tried to use the undefined elements as a hash key.

Now just by saying () = @root[0 .. 7] does not change the length of the array, it just returns undefined values where the elements do not exist. So what's happened here?

Well, the answer is that grep wants to alias the elements of the list to $_ so perl must create a scalar for them.

The same thing can happen with an array element instead of a range, or a hash slice or element. It does not happen with the print operator instead of grep It can also happen with user-defined subroutine instead of print.

There are still issues here I don't understand. I'd be glad if someone could shed some light on how come $a[1] does not exist in the following test program:

#!perl use warnings; no warnings "uninitialized"; use Dumpvalue; $D = Dumpvalue->new; sub f { print $_[0]; } sub g { $_[0] = 5; } f($a[1]); f(@a[2, 3]); g($a[5]); g(@a[6, 7]); print $a[9]; print @a[10, 11]; () = grep 0, $a[13]; () = grep 0, @a[14 +, 15]; $t = $a[17]; @t = @a[18, 19]; f($h{1}); f(@h{2, 3}); g($h{5}); g(@h{6, 7}); print $h{9}; print $h{10, 11}; () = grep 0, $h{13}; () = grep 0, @h{14 +, 15}; $t = $h{17}; @t = @h{18, 19}; $D->dumpValues(\@a, \%h); __END__
Output:
0 ARRAY(0x81495c0) 0 empty slot 1 empty slot 2 undef 3 undef 4 empty slot 5 5 6 5 7 undef 8 empty slot 9 empty slot 10 empty slot 11 empty slot 12 empty slot 13 undef 14 undef 15 undef 1 HASH(0x8192464) 13 => undef 14 => undef 15 => undef 2 => undef 3 => undef 5 => 5 6 => 5 7 => undef

Updates: changed code from one-liner to perl -x script, per suggestion of diotalevi. Also added some more readmore tags now that this is frontpaged.

Let me note that I think this is not autovivification, and I tried to explain why in a reply although my explanation isn't very clear.


In reply to Aliasing bites by ambrus

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (3)
As of 2024-04-18 18:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found