6

I'm aware of the fact that $@ is a global variable, still I can't figure out why I need to localize it before using eval:

例えば:

eval { SOME_FUNC_THAT_MAY_DIE(); };
if ($@) {
  print "An error occured!\n";
}

私が考えることができる唯一のことは、いくつかのシグナルハンドラーがdie私が読み込もうとすると同時に呼び出す場合$@、ここで何が欠けているのでしょうか?

4

3 に答える 3

12

local $@電話をかける前に言う理由evalは、発信者の を踏まないようにするため$@です。サブルーチンがグローバル変数を変更するのは失礼です (それがサブルーチンの明示された目的の 1 つでない限り)。これは実際にはトップレベル コードの問題ではありません (サブルーチン内ではありません)。

また、古い Perl では、最初にローカライズされていない限りeval、オブジェクトの破棄中に呼び出されたものはすべて (ブロック$@から例外がスローされたためにオブジェクトが破棄されていた場合)グローバルを破壊していました。これは5.14.0で修正されましたが、多くの人はまだ古い Perl を使用しています。eval$@

于 2012-07-04T19:50:04.757 に答える
9

Try::Tinyモジュールのドキュメントには、その根拠が示されています (代替手段も提供されています)。

eval ブロッ​​クを実行して成功すると、$@ がクリアされ、現在キャッチされているエラーが上書きされる可能性があります。これにより、離れた場所でアクションが発生し、呼び出し元がまだ処理していない可能性のある以前のエラーがクリアされます。この問題を回避するには、eval を呼び出す前に $@ を適切にローカライズする必要があります。より具体的には、 $@ は eval の開始時に上書きされ、これにより、死ぬ前に以前のエラーをキャプチャすることもできなくなります (たとえば、エラー スタックで例外オブジェクトを作成する場合)。
于 2012-07-04T19:47:04.073 に答える