2017-08-27 11 views
1

私のスレッドのためのファイルハンドルのテーブルを作るためにfilenoを使用しようとしていますが、私は理解できない状況に遭遇しました。filenoとリファレンス弱体化の混乱

use strict; 
use Data::Dumper; 
my %fhh; #this is shared, but that's not important for my issue 
open my $fh , '>', 'out1.txt' ; 
$fhh{1} = fileno $fh; 
open my $fh , '>', 'out2.txt' ; 
$fhh{2} = fileno $fh; 
open my $fh , '>', 'out3.txt' ; 
$fhh{3} = fileno $fh; 
open my $fh , '>', 'out4.txt' ; 
$fhh{4} = fileno $fh; 
print Dumper \%fhh; 

私が手出力は次のとおりです:

$VAR1 = { 
      '4' => '9', 
      '1' => '6', 
      '3' => '8', 
      '2' => '7' 
     }; 

これまでのところは良い、残念ながら私はハンドルの未知の番号を生成する必要があるので、私は次のコードを試してみました:

次のコードを検討
use strict; 
use Data::Dumper; 
my %fhh; 
foreach my $i (1 .. 4){ 
    my $file = "out" . $i . ".txt"; 
    open my $fh , '>', $file ; 
    $fhh{$i} = fileno $fh; 
} 
print Dumper \%fhh; 

ここで私は出力を得る:

$VAR1 = { 
      '4' => '10', 
      '1' => '10', 
      '3' => '10', 
      '2' => '10' 
     }; 

何かが間違っている、おそらくここ$ fhは弱くなって失われますか?私は次のことを試してみました:

ここ
use strict; 
use Data::Dumper; 
my %fhh; 
my @mfw; 
foreach my $i (1 .. 4){ 
    my $file = "out" . $i . ".txt"; 
    open my $fh , '>', $file ; 
    push @mfw, $fh; 
    $fhh{$i} = fileno $fh; 

} 
print Dumper \%fhh; 

出力は、第1の例のように、再び正しいですので、それは確かに弱体化の問題であるようだが、なぜ最初の例ではこの出来事ではないでしょうか?私は毎回$ fhを再定義していますが、{}でブロック全体を囲んでも、それでも問題なく動作します。
重要なことはperl 5.14です。

答えて

3

my $fhは囲むブロックにスコープがあります。この変数は、ファイルハンドルへの唯一の参照です。ファイルハンドルが破棄されると、ファイルは閉じられ、ファイル記述子番号は次のファイルに再利用されます。 FDは単なる整数で、ファイルを開いたままにする魔法はありません。

オープンされたファイルハンドルへの参照を配列内に保持することで、ファイルハンドルの有効期間が延長されました。したがって、それぞれの新しいファイルは新しいFD番号を取得します。

+0

わかりました。最初の例を4ブロックに分割してみましたが、問題は実際に発生します。ですから、同じブロック内で変数を再定義すると、以前のコンテンツは弱くならないでしょうか? – Nullman

+0

@ Nullmanコードには弱い参照はありません。 Perlはガベージコレクションを管理するために参照カウントを使用します。オブジェクトの参照カウントがゼロになると、オブジェクトは破棄されます。 'my'を持つ変数は、ブロックの終わりまでしか存在しません。ファイル記述子は、Perlが認識する参照ではありません。あなたの最後の例では、配列は破壊されないようにファイルハンドルを参照し続けます。 – amon

+1

最初の例で$ fhを再定義すると、以前に開いたファイルハンドルは、ブロックが終了するまでメモリのどこかでまだ開いていますが、ループでは各繰り返しの最後に閉じます。それはループの各反復が別々のブロックであることを意味しますか? – Nullman