-
Notifications
You must be signed in to change notification settings - Fork 571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Failure to initialize my() variables #12649
Comments
From tlhackque@yahoo.comCreated by tlhackque@yahoo.commy() variables don't initialize properly, at least as I read the doc. Documentation in PERLSUB Camel book agrees, and is more specific: BUG: Code of the form: does not initialize %x if $q is false. In fact, you seem to get the last value of %x in the current scope. There is no warning or error with use strict; and use warnings in effect; This result is clearly not what the language intends. The if() modifier makes the assignement conditional. If it's false, the variable is not assigned to, and should have the default empty value. Either the code should fail to compile, or an undefined/empty value should be supplied if the condition is false. Leaking a previous value is clearly problematic - may have serious consequences in some usages. Here is a reasonably small reproducer, distilled from a large project. The final call to Dumper should show %obj1 and %obj2 with identical state. In fact, obj2 is empty. The cause can be seen where the second printout of VAR2 shows the previous value of %present. If the initialization of %present is made a separate statement, the correct behavior is observed. E.G. my %present; %present = map { $_ => 1 } @$list if ($list); #!/usr/bin/perl use warnings; use Data::Dumper; sub add { my $list = $a->{list}; print Dumper( \@_, \%present ); foreach my $item (@_) { my %obj1; add( \%obj1, qw/ONE/ ); my %obj2; print Dumper( \%obj1, \%obj2 ); exit Annotated output: $VAR1 = [ # First call: Arg to add() Perl Info
|
From tlhackque@yahoo.comI see from the meta ticket that (unsurprsingly), I'm not the first to A little more data: We scanned the project with perlcritic and found 16 instances of this In every case, the intended semantics were my foo; foo = () if(); We didn't encounter any of the subtle scoping case I have not seen a case in real code where someone relied (much less Therefore, the minimal impact to existing code is NOT to add a compile We also got a number of hits in CPAN modules that ship with our The reason I set the severity so high is that uninitialized data is a my %task = ( logged_in => 1) if( $session->authenticated ); Based on all these observations, a core perl fix seems indicated. It would make sense to add a release note advising that Perl::Critic I hope this additional data is helpful. On Sun Dec 16 09:12:33 2012, tlhackque wrote:
3.3/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/
|
From [Unknown Contact. See original ticket]I see from the meta ticket that (unsurprsingly), I'm not the first to A little more data: We scanned the project with perlcritic and found 16 instances of this In every case, the intended semantics were my foo; foo = () if(); We didn't encounter any of the subtle scoping case I have not seen a case in real code where someone relied (much less Therefore, the minimal impact to existing code is NOT to add a compile We also got a number of hits in CPAN modules that ship with our The reason I set the severity so high is that uninitialized data is a my %task = ( logged_in => 1) if( $session->authenticated ); Based on all these observations, a core perl fix seems indicated. It would make sense to add a release note advising that Perl::Critic I hope this additional data is helpful. On Sun Dec 16 09:12:33 2012, tlhackque wrote:
3.3/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/
|
tlhackque@yahoo.com - Status changed from 'new' to 'open' |
From tlhackque@yahoo.comIn reviewing all the related items, I noted some confusion about what Here's an attempt at a precise formulation: When a my declaration includes an initializing expression, it is 1. For each item on the left hand side of the declaration, an Note that a my() declaration embedded in an if() or while() gets no my( $a, $q ) = (2, 4); is well defined under this definition, and equivalent to print ( $nil? (2+1) : 4 ); This doesn't require that the implementation goes thru all 3 steps in Some examples: my %foo = @bar if( $nil ); my( $a, $b, @c ) = ( 1, 2, @_ ) if( $nil ); A pretty ovbious generalization is that = can now be any sensible e.g. .= isn't sensible as it's guaranteed a runtime exception (undef . my $a = 11; Some obvious shortcuts: Others will come to mind. I know next to nothing about Perl internals, so if I happened to pick As always, thanks for all the effort you put into maintaining Perl. I |
From [Unknown Contact. See original ticket]In reviewing all the related items, I noted some confusion about what Here's an attempt at a precise formulation: When a my declaration includes an initializing expression, it is 1. For each item on the left hand side of the declaration, an Note that a my() declaration embedded in an if() or while() gets no my( $a, $q ) = (2, 4); is well defined under this definition, and equivalent to print ( $nil? (2+1) : 4 ); This doesn't require that the implementation goes thru all 3 steps in Some examples: my %foo = @bar if( $nil ); my( $a, $b, @c ) = ( 1, 2, @_ ) if( $nil ); A pretty ovbious generalization is that = can now be any sensible e.g. .= isn't sensible as it's guaranteed a runtime exception (undef . my $a = 11; Some obvious shortcuts: Others will come to mind. I know next to nothing about Perl internals, so if I happened to pick As always, thanks for all the effort you put into maintaining Perl. I |
From @cpansproutOn Mon Dec 17 08:06:40 2012, tlhackque wrote:
The problem here is that in ‘my $x if $false’ the ‘my $x’ is never executed. ‘my $x’ conceptually creates the scalar, so ‘my $x if 0; $x’ ends up I agree this should be fixed, but I disagree that it is high priority. BTW, this is how you can tell perl is reusing the scalar: $ perl -le 'for(1..5) { print \my $x }' But it knows how to hide that fact when the scalar is referenced elsewhere: $ perl -le 'for(1..5) { print \my $x; push @_, \$x }' -- Father Chrysostomos |
From @ap* Father Chrysostomos via RT <perlbug-followup@perl.org> [2012-12-23 22:10]:
Note that the problem can only possibly happen with a statement modifier my $x = "foo" if $y; into the equivalent of my $x; Although now I remember groans about op tree diddling being fragile code (Please disregard if this is all nonsense.) |
From @iabynOn Mon, Dec 24, 2012 at 01:30:15AM +0100, Aristotle Pagaltzis wrote:
There's also goto FOO; -- |
From @ap* Dave Mitchell <davem@iabyn.com> [2012-12-24 21:55]:
Nasty. I guess optree diddling is off the table. |
Migrated from rt.perl.org#116110 (status was 'open')
Searchable as RT116110$
The text was updated successfully, but these errors were encountered: