On Mon, 28 Apr 2008 01:45:43 +0200, Matt Sergeant <matt@sergeant.org> wrote: > (I did post this via perlbug and to perlbug@perl.org but both appear to > have gone into a black hole) Did you send them from the same emailaddress as this message? > > The following code: > > if (open(my $fh, "/etc/passwd")) { > ... > } > > Leaves the file open at the exit of the scope (in fact to the end of the > program). But $fh is out of scope, meaning the file should be closed. > > (you can confirm with system(qq(ls -l /proc/$$/fd)) on Linux) > > Using: > > do { my $fh; > if (open($fh, "/etc/passwd")) { > ... > } > } > > Does the right thing and closes the file handle at the end of the scope, > but that's ugly. > > (confirmed on both 5.10 and 5.8) > > Matt. Confirmed with blead. For example: #!/usr/bin/perl use strict; use warnings; my $foo = 1; if (open(my $fh, "/etc/passwd") and ! $foo) { # ... } elsif ($foo) { print while <$fh>; } system(qq(ls -l /proc/$$/fd)); __END__ Will print the contents of /etc/passwd. Followed by: total 0 lrwx------ 1 bram users 64 2008-04-28 09:11 0 -> /dev/pts/2 lrwx------ 1 bram users 64 2008-04-28 09:11 1 -> /dev/pts/2 lrwx------ 1 bram users 64 2008-04-28 09:11 2 -> /dev/pts/2 lr-x------ 1 bram users 64 2008-04-28 09:11 3 -> /etc/passwd lr-x------ 1 bram users 64 2008-04-28 09:11 4 -> pipe:[462056431] Putting it in another block does make the fh go out of scope. #!/usr/bin/perl use strict; use warnings; { my $foo = 1; if (open(my $fh, "/etc/passwd") and ! $foo) { # ... } elsif ($foo) { print while <$fh>; } } system(qq(ls -l /proc/$$/fd)); __END__ (Small note: you do not need the do) Will print the contents of /etc/passwd Followed by: total 0 lrwx------ 1 bram users 64 2008-04-28 09:11 0 -> /dev/pts/2 lrwx------ 1 bram users 64 2008-04-28 09:11 1 -> /dev/pts/2 lrwx------ 1 bram users 64 2008-04-28 09:11 2 -> /dev/pts/2 lr-x------ 1 bram users 64 2008-04-28 09:11 3 -> pipe:[462053596] Of course this fails: #!/usr/bin/perl use strict; use warnings; if (open(my $fh, "/etc/passwd")) { # ... } print while <$fh>; system(qq(ls -l /proc/$$/fd)); __END__ Global symbol "$fh" requires explicit package name at x.pl line 9. Execution of x.pl aborted due to compilation errors. Another, perhaps easier to test, example: #!/usr/bin/perl -l use strict; use warnings; { if (my $foo = bless { }, "Foo") { print "in if"; } print "End of block"; } print "After block"; package Foo; DESTROY { print "Foo destroyed"; } Outputs: in if End of block Foo destroyed After block Which (to me) means that $foo - incorrectly - gets freed after the block and not after the if. Kind regards, BramThread Previous | Thread Next