6

オブジェクトがDESTROYグローバル破壊の一部として実行されているかどうかを検出し、警告を出力したいと思います(これは明らかにエラーであり、データの損失につながるため)。それを行うための明白な方法は次のように思われます:

sub DESTROY {
    my $self = shift;
    # ⋮
    if (i_am_in_global_destruction()) {
        warn "I survived until global destruction";
    }
}

しかし、私はグローバルな破壊を検出するための良い方法を見つけることができませんでした(通常のrefcountヒット0の破壊の代わりに)。

「良い方法」とは、これではないことを意味します。これは、5.10.1および5.8.8で機能しますが、誰かが奇妙な一見を与えたときにおそらく壊れます。

sub DESTROY {
    $in_gd = 0;
    {
        local $SIG{__WARN__} = sub { $_[0] =~ /during global destruction\.$/ and $in_gd = 1 };
        warn "look, a warning";
    }
    if ($in_gd) {
        warn "I survived until global destruction";
    }
}'
4

2 に答える 2

11

モジュールDevel::GlobalDestructionがあります。このモジュールは、XSのごく一部を使用して、グローバル破棄フラグを直接取得できるようにします。

更新:perl 5.14.0以降、グローバル破棄中${^GLOBAL_PHASE}に設定されるグローバル変数があります"DESTRUCT"。5.6までのperlsで機能するため、通常はDevel::GlobalDestructionを使用する必要があります。それを使ってperlにインストールする${^GLOBAL_PHASE}場合、組み込み機能を使用し、ビルドにCコンパイラを必要としません。

于 2011-02-04T20:48:15.507 に答える
8

私にとって十分な解決策は、ENDブロックにフラグを設定することです。

package Whatever;
our $_IN_GLOBAL_DESTRUCTION = 0;
END {
    $_IN_GLOBAL_DESTRUCTION = 1;
}
于 2011-02-04T21:04:20.270 に答える