は、セグメンテーションフォールトを検出するためのサポートを追加することによって、この便利な、私は拡張していますtobyinkの答えを見つけました。私が発見した2つのアプローチがあります。逆参照の前に、$SIG{SEGV}
と$SIG{BUS}
をローカルに置き換える最初の方法があります。第2の方法はmasks the child signalで、分岐した子が逆参照できたかどうかを確認します。最初の方法は2番目の方法よりも大幅に高速です。
誰でもこの回答を改善することができます。
最初のアプローチ
sub unstringify_ref($) {
use bigint qw(hex);
use Devel::FindRef;
my $str = @_ ? shift : $_;
if (defined $str and $str =~ /\((0x[a-fA-F0-9]+)\)$/) {
my $addr = (hex $1)->bstr;
local [email protected];
return eval {
local $SIG{SEGV} = sub { die };
local $SIG{BUS} = sub { die };
return Devel::FindRef::ptr2ref $addr;
};
}
return undef;
}
私は他の信号が不正なメモリにアクセスしようとする試みに発生する可能性がありますかはわかりません。
第二のアプローチ
sub unstringify_ref($) {
use bigint qw(hex);
use Devel::FindRef;
use Signal::Mask;
my $str = @_ ? shift : $_;
if (defined $str and $str =~ /\((0x[a-fA-F0-9]+)\)$/) {
my $addr = (hex $1)->bstr;
local $!;
local $?;
local $Signal::Mask{CHLD} = 1;
if (defined(my $kid = fork)) {
# Child -- This might seg fault on invalid address.
exit(not Devel::FindRef::ptr2ref $addr) unless $kid;
# Parent
waitpid $kid, 0;
return Devel::FindRef::ptr2ref $addr if $? == 0;
} else {
warn 'Unable to fork: $!';
}
}
return undef;
}
私はwaitpid
の戻り値がチェックする必要があるかはわかりません。
「Dumper($ b)」を超えてどのような魔法が必要なのか分かりません。明らかにあなたは '警告する 'ことを望む。あなたはいつ警告しますか? '$ a'を文字列化することができるほとんどの場所で、私は' $ a'をダンプします。 – Axeman
文字列をオーバーロードして番号を返す方が簡単です。 – MkV
'eval $ thing'がほしいと思うように聞こえます。もちろん、これは文字列化された方法に依存します。 Data :: DumperまたはData :: Dumpを使用した場合、単に 'eval'ingするとオブジェクトが再作成されます。 – simbabque