2012-05-08 35 views
4

這是一個令我感到困惑的問題,我的同事有。而且我也無法找出原因。Perl不會在對象銷燬時調用DESTROY的情況?

簡短版本是在他寫的一個類中定義了DESTROY析構函數/方法,DESTROY在對象被銷燬時沒有被調用。它不會在我們認爲物體超出範圍的地方被召喚。雖然我們認爲可能在某處有一個懸而未決的引用,但它在腳本出口處也不會被調用。我們通過調試print語句來散佈類和腳本,甚至在END塊中明確地調用了它,以驗證我們沒有將它放入錯誤的名稱空間。 (我們沒有,明確的電話觸發了預期的所有print報表。)

所以我對此感到困惑,並且對答案和他一樣感興趣。什麼情況可能導致這種行爲?有問題的腳本正在退出乾淨 - 沒有電話POSIX::_exit或類似的東西。這裏唯一的「變量」是類正在使用Class::MethodMaker來定義一些訪問器和構造函數。但是,Class::MethodMaker文檔中沒有提及與(或覆蓋)類DESTROY方法的交互。

+0

有沒有可能發佈代碼?我已經使用了C :: MM,並沒有看到這種行爲。所有人都在尋找相同的起點來試圖弄清楚發生了什麼,這將是有益的。 –

回答

6

沒有看到代碼,人們不知道發生了什麼問題。但我能想象這樣一個場景,它會像你的destroy()方法是不叫:

#!/usr/bin/perl 

use strict; 
use warnings; 

sub DESTROY { 
    die {}; 
    print "DESTROY\n"; 
} 

{ 
    print "creating object...\n"; 
    my $obj = bless {}; 
    print "it goes out of scope...\n"; 
} 

print "object is out of scope\n"; 

此腳本會打印:

creating object... 
it goes out of scope... 
object is out of scope 

也許,誤差不作爲在這個例子中那樣明顯。 die()調用可能在DESTROY代碼中很深。

die()調用可能是由某種你沒有想到的情況引起的。對象是全球毀滅期間以任意順序undef'ed:

#!/usr/bin/perl 

use strict; 
use warnings; 

sub DESTROY { 
    die {} if ! defined $_[0]->[0]; 
    print "$_[0]->DESTROY()\n"; 
} 

print "creating objects...\n"; 
my $x = bless []; 
my $y = bless [$x]; 
$x->[0] = $y; 
print "before global destruction...\n"; 

循環引用不necessarry要做到這一點。其中一個對象檢查它是否可以訪問另一個對象。如果訪問失敗,則拋出異常。

H2H,馬蒂亞斯

+0

歡迎來到SO,感謝您的好評! – Ashe

6

還有另一種方法DESTROY不叫這不是特別明確記載。它只會影響你,如果你正在編寫守護進程等。從本質上講,如果你的進程由於信號而死亡(甚至是CTRL-C,它實際上是SIGINT),那麼它將不會調用DESTROY方法。您可以通過使用僅調用exit()的信號處理程序來實現此目的。在下面的示例中,如果程序正常退出或收到SIGTERM,則調用DESTROY()方法:

sub _signal_handler { 
    exit(0); 
} 

sub new { 
    my ($class) = @_; 
    my $self = {}; 
    bless $self, $class; 
    SIG{'TERM'} = \&_signal_handler; 
    return $self; 
} 

sub DESTROY { 
    my ($self) = @_; 
    print "Destroy method called\n"; 
} 
+0

如果可能,您是否可以鏈接到詳細描述此行爲的資源?如果有任何後續問題,這可能是有價值的。 – c0dem4gnetic

相關問題