这是我的同事所面临的一个令人困惑的问题.而且我也无法解决问题.
在他编写的类中,简短版本具有DESTROY
定义的析构函数/方法,DESTROY
在对象被销毁时不会被调用.在我们认为对象超出范围的时刻,它不会被调用.虽然我们认为可能在某个地方有一个悬空引用它,但它也没有在脚本退出时被调用.我们用调试print
语句乱写了类和脚本,甚至在END
块中对它进行了显式调用,只是为了验证我们没有以某种方式将它放在错误的命名空间中.(我们没有.显式调用print
按预期触发了所有语句.)
所以我对此感到困惑,并且他对答案的兴趣与他一样.什么情况可能导致这种行为?有问题的脚本正在彻底退出 - 没有任何电话POSIX::_exit
或类似的东西.这里唯一的"变量"是该类Class::MethodMaker
用于定义一些访问器和构造函数.但是,Class::MethodMaker
文档中没有引用与类DESTROY
方法交互(或覆盖)的方法.
没有看到代码,就无法知道出了什么问题.但是我可以想象一下这样一个场景:看起来你的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";
Run Code Online (Sandbox Code Playgroud)
这个脚本打印:
creating object...
it goes out of scope...
object is out of scope
Run Code Online (Sandbox Code Playgroud)
可能,错误并不像本例中那么明显.die()调用可能在DESTROY代码中很深.
die()调用可能是由您没有想到的某些条件引起的.在全局破坏期间,对象以任意顺序未定义:
#!/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";
Run Code Online (Sandbox Code Playgroud)
循环引用并非必须发生这种情况.其中一个对象检查它是否可以访问另一个对象.如果访问失败,则抛出异常.
h2h,马蒂亚斯
小智 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";
}
Run Code Online (Sandbox Code Playgroud)