检测Perl中的全局破坏

der*_*ert 5 perl destroy

我想检测我的对象是否DESTROY作为全局破坏的一部分,并打印出警告(因为这显然是一个错误并导致数据丢失).显而易见的方法似乎是:

sub DESTROY {
    my $self = shift;
    # ?
    if (i_am_in_global_destruction()) {
        warn "I survived until global destruction";
    }
}
Run Code Online (Sandbox Code Playgroud)

但我一直无法找到一种检测全局破坏的好方法(而不是正常的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";
    }
}'
Run Code Online (Sandbox Code Playgroud)

hob*_*bbs 10

有一个模块Devel :: GlobalDestruction,它使用一点点XS让你直接得到全局销毁标志.

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

  • 谢谢!它甚至为Debian打包为"libdevel-globaldestruction-perl",因为Lenny不会少. (2认同)

mob*_*mob 8

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

package Whatever;
our $_IN_GLOBAL_DESTRUCTION = 0;
END {
    $_IN_GLOBAL_DESTRUCTION = 1;
}
Run Code Online (Sandbox Code Playgroud)

  • 此外,在完成所有END块之后,技术上会发生全局破坏 - 因此最糟糕的情况是,它可能在另一个END块中被销毁时标记错误. (4认同)