2

私は多くのことを行うオブジェクトを持っており、何が起こったのかについての統計を表示する TidyUp() メソッドを呼び出して終了します。

内部テストの一環として、これらのオブジェクトがいつ作成されたかを検出したかったのですが、プログラムが終了する前に片付けられず、その場合は終了しました。

そこで、TidyUP() で設定されるオブジェクトにフラグを追加し、このフラグが設定されていない場合に死ぬクラスの DESTROY サブルーチンを追加しました。

これはすべて正常に機能しますが、残念な副作用があります。プログラムで何か他の問題が発生し、die が呼び出されると、グローバルな破壊が私の DESTROY を起動し、オブジェクトが整理されていないことに気づき、死亡します。問題は、この時点で元のダイ メッセージが失われていることです。

したがって、破壊がダイの結果として発生したのか、それとも通常のプログラムの終了によるものなのかを検出し、後者の場合にのみ新しいダイを追加したいと思います。

Perl でのグローバル破壊の検出を見てみましたが、何がグローバル破壊を引き起こしたのかを検出したいので、それは役に立たないと思います。

4

3 に答える 3

0

$SIG{__DIE__}グローバル例外ハンドラーにフックできます。

#!/usr/bin/perl
use Modern::Perl;

package Foo;
my $DIED = 0;
BEGIN { $SIG{__DIE__} = sub { $DIED = 1 }; }

sub new { bless [0] }
sub DESTROY { die 'untidy' unless shift->[0] or $DIED }
sub tidy_up { shift->[0] = 1 }

package main;
my $foo = new Foo;
die if @ARGV; # line 13
$foo->tidy_up();
say 'success';

$ perl test.pl
success

$ perl test.pl die
Died at test.pl line 13.

その例外ハンドラはグローバルにインストールされるため、既存のエラーハンドラを上書きしないように注意してください。Signals::XSIGはそれを支援します。

于 2013-01-10T21:39:58.367 に答える
0

この問題をいじってみると、プログラムの終了方法によって、メソッドのコール スタックDESTROYがわずかに異なることがわかります。多分それは助けることができます:

package Foo;
sub new { bless [], __PACKAGE__ }
sub DESTROY {
    my ($n,$pkg,$file,$line);
    while (my @c=caller($n++)) {
        ($pkg,$file,$line) = @c;
    }
    print STDERR "DESTROY called via $file line $line\n";
}
my $foo = Foo->new;
if ($ARGV[0] eq 'die') { die }       # line 11
if ($ARGV[0] eq 'exit') { exit }     # line 12
# else passive exit

$ perl 14255585.pl die
Died at 14255585.pl line 11.
DESTROY called via 14255585.pl line 11

$ perl 14255585.pl exit
DESTROY called via 14255585.pl line 12

$ perl 14255585.pl foo
DESTROY called via 14255585.pl line 0

プログラム内の終了点のリストが小さく、明確に定義されている場合は、それらを列挙して、プログラムの終了時に処理することができます。それ以外の場合は、オンザフライで静的コード分析を実行して、考えられる死因を確認できます。

于 2013-01-10T16:01:28.657 に答える
0

オブジェクトが整理されているかどうかを確認する前に、グローバル フラグを設定できます。これで、プログラムがどのフェーズで実行されているかがわかります。を使用してプログラムが終了したときにコールバックを登録することもできます$SIG{__DIE__}$?他の方法で設定できるため、チェックは安全ではありません。あなたが地球規模で破壊されているかどうかを確認することもうまくいくはずです. しかし、最もクリーンな解決策は、整理する必要があるすべてのオブジェクトを追加の配列に格納することです。その後、必要なときにいつでもこれらのオブジェクトをループして、 を使用しなくて済みDESTROYます。

于 2013-01-10T14:17:15.750 に答える