检测Perl中的全局破坏

时间:2011-02-04 20:43:46

标签: perl destroy

我想检测我的对象是否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";
    }
}'

2 个答案:

答案 0 :(得分:10)

有一个模块Devel::GlobalDestruction使用一点点XS来让你直接获得全局销毁标记。

更新:自perl 5.14.0以来,全局变量${^GLOBAL_PHASE}将在全局销毁期间设置为"DESTRUCT"。你仍然应该使用Devel :: GlobalDestruction,因为它可以与perls一起使用回5.6。在使用${^GLOBAL_PHASE}的perl上安装时,它将使用内置功能,甚至不需要构建C编译器。

答案 1 :(得分:8)

对我来说足够好的解决方案是在END块中设置标记。

package Whatever;
our $_IN_GLOBAL_DESTRUCTION = 0;
END {
    $_IN_GLOBAL_DESTRUCTION = 1;
}