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

Hi guys,

I noticed that if I'm using several uninitialized variables in a string, and if at least one of those variables is a hash, then the name of the hash only appears in the warnings if it's the first uninitialized variable of the string.

For example
#!/usr/bin/perl use warnings; my (%a, %b, $c); my $x = "$a{'foo'} $b{'bar'} $c"
prints the following warnings:
Use of uninitialized value $a{"foo"} in concatenation (.) or string at + main.pl line 5. Use of uninitialized value in concatenation (.) or string at main.pl l +ine 5. Use of uninitialized value $c in concatenation (.) or string at main.p +l line 5.

You'll notice that the name of the variables $a{"foo"} and $c appear in the 1st and 3rd warnings, but the name of $b{"bar"} doesn't appear in the 2nd warning.

Is there a good reason for that or is it a defect ?

Replies are listed 'Best First'.
Re: Variable name missing in warning
by bigj (Monk) on Apr 02, 2014 at 16:48 UTC
    Allthough I originally wrote a module like Test::Warn, I wasn't aware of that behaviour. However perldiag describes it as a kind of optimization:
    Use of uninitialized value%s (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl will try to tell you the name of the variable (if any) that was undefined. In some cases it cannot do this, so it also tells you what operation you used the undefined value in. Note, however, that perl optimizes your program and the operation displayed in the warning may not necessarily appear literally in your program. For example, "that $foo" is usually optimized into ""that " . $foo", and the warning will refer to the "concatenation (.)" operator, even though there is no "." in your program.

    Greetings,
    Janek

      I checked with B::Deparse and B::Concise and the variable name is clearly visible i.e not optimized away:

      > perl -MO=Deparse,-q use warnings; my (%a, %b, $c); my $x = "$a{'foo'} $b{'bar'} $c" __END__ use warnings; my(%a, %b, $c); my $x = $a{'foo'} . ' ' . $b{'bar'} . ' ' . $c; - syntax OK

      -q reveals the mentioned optimization of string-interpolations, but the variable name is not affected.

      I thought this is only a negligible bug, such that after fixing $a{foo} the following $b{bar} would be visible, but that's unfortunately not the case:

      > perl -w my (%a, %b, $c); $a{foo}="FIXED"; my $x = "$a{'foo'} $b{'bar'} $c"; __END__ Use of uninitialized value in concatenation (.) or string at - line 3. Use of uninitialized value $c in concatenation (.) or string at - line + 3.

      Cheers Rolf

      ( addicted to the Perl Programming Language)

        Then why don't you (anybody in this thread) go read (and understand) the near-400-line subroutine of C code that tries to find variable names for undef warnings?

        See S_find_uninit_var in sv.c.

        The docs didn't say that sometimes variable names are optimized away (the mention of optimization was about the reported operation). The docs pretty clearly hint (to me, anyway) that finding the variable name isn't close to a trivial task and is known to fail somewhat often for reasons too complicated to usefully summarize in those docs.

        - tye        

      This says that optimizations (compile time optimizations I guess) can explain why perl doesn't know exactly in what operation the variable was used.

      But this doesn't say why perl would not know the name of the variable.

Re: Variable name missing in warning
by toolic (Bishop) on Apr 02, 2014 at 16:33 UTC
    UPDATE: Nevermind. As bigj states, perldiag has this covered.

    Looks like a bug to me. I also see it, and I'm on perl version 5.14.2. How recent is your perl? perlbug

      v5.16.1 yields the same.

      same v5.10.0

      Cheers Rolf

      ( addicted to the Perl Programming Language)

      I'm using 5.14.2 too.