perl - Why does encode raise "Use of uninitialized value within @_"? -
with perl v5.14.2 (provided debian wheezy) code:
use encode qw(encode); no warnings "all"; sub test_encode { return encode::encode("utf8", $_[0]); } $a=undef; $r=test_encode(substr($a,0,1));
produces empty string in $r
. i'm fine that.
with perl 5.18.2 (ubuntu 14.04), appears produces output:
use of uninitialized value within @_ in list assignment @ /usr/lib/perl/5.18/encode.pm line 147.
(even warnings disabled in main scop, apparently it's not warning. edit: per answers, it's warning):
that list assignment be, in encode.pm
:
146 sub encode($$;$) { 147 ( $name, $string, $check ) = @_; 148 return undef unless defined $string; 149 $string .= ''; # stringify;
tweaking code, if undef
passed encode
instead of $_[0]
, no longer complains. if copy of $_[0]
in temp variable passed instead of $_[0]
, doesn't complain too.
my question are: have changed in perl between these versions explain new behavior? perl see inside @_
in encode.pm line 147 ?
addendum: adding dump($_[0]);
devel::peek
@ start of test_encode
, outputs:
perl 5.14.2:
sv = pvlv(0x23a2c10) @ 0x2340998 refcnt = 1 flags = (gmg,smg) iv = 0 nv = 0 pv = 0 magic = 0x235f950 mg_virtual = &pl_vtbl_substr mg_type = perl_magic_substr(x) type = x targoff = 0 targlen = 0 targ = 0x235e370 sv = pv(0x233ec20) @ 0x235e370 refcnt = 2 flags = (padmy,pok,ppok) pv = 0x23576b0 ""\0 cur = 0 len = 16
perl 5.18.2:
sv = pvlv(0x25c07c0) @ 0x2546cb8 refcnt = 1 flags = (gmg,smg) iv = 0 nv = 0 pv = 0 magic = 0x2567dd0 mg_virtual = &pl_vtbl_substr mg_type = perl_magic_substr(x) type = x targoff = 0 targlen = 1 targ = 0x256f328 flags = 0 sv = null(0x0) @ 0x256f328 refcnt = 2 flags = (padmy)
not sure think of that, sv
part @ end differs significantly, looks empty string versus null(0x0).
it's substr
that's warning.
substr
warns when first argument undefined.
$ perl -we' $x; $y = substr($x, 0, 1); # line 3 ' use of uninitialized value $x in substr @ -e line 3.
since 5.16.0, warning happens when substring operation performed instead of when substr
called. when substr
used lvalue, actual substring operation performed when value fetched or stored in returned scalar.
$ perl -we' $x; $r = \substr($x, 0, 1); $y = $$r; # line 4 ' use of uninitialized value in scalar assignment @ -e line 4.
the substring operation done allow following work:
$ perl -we'$_ = "abc"; substr($_, 0, 1) = "!!!"; say' !!!bc
since warning happens when substring operation done, it's context of op in encode determines whether warning visible or not.
$ 5.14.2t/bin/perl -e'use warnings; $r = \substr(my $x, 0, 1); no warnings; $y = $$r;' use of uninitialized value in scalar assignment @ -e line 1. $ 5.14.2t/bin/perl -e'no warnings; $r = \substr(my $x, 0, 1); use warnings; $y = $$r;' $ 5.22.0t/bin/perl -e'use warnings; $r = \substr(my $x, 0, 1); no warnings; $y = $$r;' $ 5.22.0t/bin/perl -e'no warnings; $r = \substr(my $x, 0, 1); use warnings; $y = $$r;' use of uninitialized value in scalar assignment @ -e line 1.
why did warning starting happening substring operation perform instead of when substr
called? i'm guessing, might fix following , similar problems:
$ perl -we' $x = "def"; $r = \substr($x, 0, 1); $x = "abc"; "<$$r>"; ' <a> $ 5.14.2t/bin/perl -we' $x; $r = \substr($x, 0, 1); $x = "abc"; "<$$r>"; ' use of uninitialized value $x in substr @ -e line 4. <> $ 5.22.0t/bin/perl -we' $x; $r = \substr($x, 0, 1); $x = "abc"; "<$$r>"; ' <a>
prefixing substr
scalar
calls rvalue, though that's not documented.
$ perl -mo=concise,-exec -e'1 substr($_, 0, 1)' 2>&1 | grep substr 7 <@> substr[t4] skm/3 ^ flag causes special lvalue behaviour. $ perl -mo=concise,-exec -e'1 scalar substr($_, 0, 1)' 2>&1 | grep substr 7 <@> substr[t2] sk/3
you force stringification.
$ perl -mo=concise,-exec -e'1 "".substr($_, 0, 1)' 2>&1 | grep substr 8 <@> substr[t2] sk/3
Comments
Post a Comment