2011-02-04 139 views
5

我想檢測我的對象是否爲DESTROY'作爲全局破壞的一部分,並打印出警告(因爲這顯然是錯誤並導致數據丟失)。最明顯的方式做到這一點似乎是:在Perl中檢測全局破壞

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

,但我一直無法找到檢測到全球毀滅的好方法(而不是普通的引用次數命中0破壞)。

通過「好辦法」,我的意思不是這個,這雖然它適用於5.9.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"; 
    } 
}' 
+0

爲什麼不簡單地保存你的對象內容時,它是DESTROYed,而不用擔心它是否在全球破壞或不是? – Ether 2011-02-04 21:12:30

+0

@Ether:因爲全局破壞的順序是未定義的,所以我需要其他對象來保存我的東西。 – derobert 2011-02-04 21:30:21

+3

我看到(來自`Devel :: GlobalDestruction`源)在v5.13.7中有一個[`{{^ GLOBAL_PHASE}`](http://search.cpan.org/~jesse/perl-5.13.9 /pod/perl5137delta.pod#New_global_variable_${^GLOBAL_PHASE})變量適合此目的。 – mob 2011-02-04 21:45:38

回答

10

有一個模塊Devel::GlobalDestruction使用一點XS讓你直接進入全局破壞標誌。

更新:因爲perl 5.14.0有一個全局變量${^GLOBAL_PHASE}將全球毀滅期間被設置爲"DESTRUCT"。你仍然應該通常使用Devel :: GlobalDestruction,因爲它可以與Perl一起工作到5.6。在使用${^GLOBAL_PHASE}的perl上進行安裝時,它將使用內置功能,甚至不需要C編譯器即可構建。

8

對我來說足夠好的解決方案是在END塊中設置一個標誌。

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