in reply to "uninitialized value in subroutine exit" warning from CGI.pm

Interesting, the only Google result for "uninitialized value in subroutine exit" (with quotes) is currently this thread. Here's an SSCCE to reproduce:

#!perl -w use warnings; use strict; use CGI; print "$] $CGI::VERSION\n"; sub Foo::get_end_date { return undef } my $pa = bless {}, 'Foo'; print CGI->new->textfield(-name=>"end_date", -default=>substr($pa->get_end_date(),0,10)), "\n"; __END__ 5.026000 4.36 Use of uninitialized value in subroutine exit at .../CGI.pm line 472. <input type="text" name="end_date" />

And a minimal test case is

$ perl -wle 'sub x{@_} print x(substr undef,0)'

On Perl 5.6 thru 5.14, this dies with "Use of uninitialized value in substr at -e line 1. Modification of a read-only value attempted at -e line 1." (which also doesn't seem quite right to me), whereas on Perls 5.16 thru 5.26 it gives the warning "Use of uninitialized value in subroutine exit at -e line 1.". A bisect shows the behavior changed with commit a74fb2cdc8f2. <update> I'm not an expert on the internals so I don't know if that commit is a red herring, or if the change was an unintended side effect of that commit, there is another commit that explains the change better, or something else. See replies. </update> Perl v5.16 was also the release of the "substr lvalue revamp", so I suspect a lot of code related to substr was modified. The release notes also say:

Passing a substring of a read-only value or a typeglob to a function (potential lvalue context) no longer causes an immediate "Can't coerce" or "Modification of a read-only value" error. That error occurs only if the passed value is assigned to.

Like LanX I suspect the whole thing has to do with the fact that substr is magical and returns a special lvalue that can modify the original string, in combination with the elements of @_ being aliases to the original parameters (Update before posting: as also said here by dave_the_m, who has deep knowledge of the internals). <update> I don't know what's going on at subroutine exit that would trigger the warning, but this issue may even be worth mentioning on P5P. See replies. </update> A few more comments on your code:

Replies are listed 'Best First'.
Re^2: "uninitialized value in subroutine exit" warning from CGI.pm
by dave_the_m (Monsignor) on Nov 10, 2017 at 15:26 UTC
    I don't know what's going on at subroutine exit that would trigger the warning
    On subroutine return, any return values are copied. If you return a substr lvalue, this will trigger the uninit warning at this point. For example this warns:
    sub f { $_[0] } $a = f(substr(undef,0,1));
    This is behaviour I would expect, and I'm not seeing a bug.

    Dave.

      On subroutine return, any return values are copied. [emphasis mine]

      D'oh! Thank you for the enlightenment on a Friday afternoon ;-)

      Update: Yep:

      $ perl -wMstrict *a = \substr(undef,0); # alias via glob $b = $a; # copy $a = 'x'; # assignment __END__ Use of uninitialized value in scalar assignment at - line 2. Modification of a read-only value attempted at - line 3.

      And just like above, on Perls <5.16 that dies with "Modification of a read-only value attempted at - line 1." (instead of line 3). So I should probably call the commit I referenced a bugfix! :-)

      Additional updates: Expanded the code example from the original version and added (and edited) the last paragraph.

Re^2: "uninitialized value in subroutine exit" warning from CGI.pm
by LanX (Saint) on Nov 10, 2017 at 14:23 UTC
    on a side note, the warning doesn't appear inside the debugger

    C:\Windows\system32>perl -e "use warnings; sub x{@_} print x(substr un +def,0)" Use of uninitialized value in subroutine exit at -e line 1. C:\Windows\system32>perl -de0 Loading DB routines from perl5db.pl version 1.37 ... DB<1> use warnings; sub x{@_} print x(substr undef,0) DB<2> print $] 5.016003

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!