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,
Bram
Thread Previous
|
Thread Next