12

デバッガーの外部で正常に実行されるPerlコードがいくつかあります。

% perl somefile.pl

しかし、デバッガー内で実行すると、次のようになります。

% perl -d somefile.pl

動作が異なります。

問題のファイル(いくつかあります)は、大規模なPerlモジュール(約2万行のコード)のテストスイートの一部です。テストはコンパイル時に多くのセットアップ作業を行い、BEGINブロックを使用します。最小限の複製コードを次に示します。

BEGIN
{
  package MyEx;

  sub new { bless {}, shift }

  package main;

  eval { die MyEx->new };

  if($@)
  {
    die "Really die"  unless($@->isa('MyEx'));
  }
}

print "OK\n";

それを入れてsomefile.pl実行すると、期待通り「OK」と表示されます。を使用してデバッガーで実行すると、次のperl -d somefile.plエラーで終了します。

Can't call method "isa" without a package or object reference ...

結果として$@、コードがデバッガーで実行される場合、それはオブジェクトではありません。代わりに、これは次の文字列を含む祝福されていないスカラーです。

" at somefile.pl line 9
    eval {...} called at somefile.pl line 9
    main::BEGIN() called at somefile.pl line 16
    eval {...} called at somefile.pl line 16
"

(内部の改行と間隔は保持されます。これは文字通りのテキストであり、「...」も含まれます。)

デバッガーで実行するには、このようなコードが必要です。テストスイートでデバッガーを使用することは、私のワークフローの重要な部分です。モジュールは例外オブジェクトを使用し、コンパイル時に多くのことを実行し、スローされたオブジェクトがキャッチされたときにオブジェクトであると想定します。

私の質問は(最後に)これ​​です:どうすればこれを機能させることができますか?回避策はありますか?これはperlデバッガモジュールのバグですか?これを解決するための最善の方法は何ですか?(私はそれがいくつかの質問であることを知っていますが、それらはすべて関連しています。)

Mac OSX10.5.5でperl5.10.0を使用しています。


Adam Bellaireによって提案されたdieLevelのことは有望に見えました、そして確かに何か(何を見つけることができないか)が私にとってそれを1に設定しています。しかし、~/.perldbファイルを使用して0に設定すると、問題が解決しません。実際、関連する3つの設定すべてを0に設定しました。私の~/.perldbファイル:

parse_options('dieLevel=0 warnLevel=0 signalLevel=0');

oデバッガーでコマンドを実行して、設定が有効になっていることを確認しました。perl -de 0実行時と実際のファイルの実行時に、すべて0に設定されているのがわかりsomefile.plます。


ありがとう、ブライアン。以前perlbugはバグ(RT 60890local $SIG{'__DIE__'} )を報告していましたが、コード内の適切な場所すべてに散らばり始めました。(バグの中で、デフォルトが0perldoc perldebugであることを示唆しているようにも見えます。 )dieLevel

4

3 に答える 3

14

これは perl5db.pl 作成__DIE__ハンドラの問題です。でローカライズ$SIG{__DIE__}するとeval、期待どおりに動作します。

評価 {
    ローカル $SIG{__DIE__};
    死ぬ MyEx->new
    };

そうしないと、Carp::longmess を使用する DB::dbdie からハンドラーを取得することになります。dieLevel が 0 の場合は発生しないはずですが、デフォルトでは 1 であり、定義されていない場合は 1 に設定されます。これは 2001 年の perl5db.pl へのパッチで、以前はデフォルトが 0 でした。

これをオフにすることになっています:

PERLDB_OPT="dieLevel=0" perl5.10.0 -d program

しかし、その後にまだコード参照があり$SIG{__DIE__}、それは dbdie への参照です。$prevdieこれは、 perl5db.pl のグローバル変数を処理する際のバグだと思いますdieLevel。そのサブルーチンの最後には、次のものがあります。

# perl5db.pl dieLevel、7777 行付近
       elsif ($prevdie) {
            $SIG{__DIE__} = $prevdie;
            print $OUT "デフォルトのダイハンドラーが復元されました。\n";
        }

$SIG{__DIE__}ただし、 を復元した後、以前の値が に保持されることに注意してください。つまり$prevdie、そこにあるものはすべて別の呼び出しにリークします。そのコマンド ラインを実行すると、処理する前に dieLevel が 2 回呼び出されるPERLDB_OPTため、$prevdieおそらくダーティです。

それで、私が perl5db.pl についてもう考えたくなかったのはこれまでのことです。

于 2008-11-27T13:36:15.177 に答える
5

デバッガーでコードが異なる動作をするときはいつでもバグだと思います。

問題はこれに関連している可能性があります:デバッガーがシンボル テーブルの変更を破損します。基本的に、デバッガーはいくつかのトリックを実行しているように見えますlocal-おそらく、対話性を提供するためのサンドボックス化の一部として. 明らかに、シンボル テーブルをいじると、予期しない副作用が発生する可能性があります。デバッガーがローカライズ$@しているため、オブジェクトが不明瞭になっていると思います。回避策が思いつきません。

于 2008-11-26T23:01:19.173 に答える
3

デバッガーPERLDB_OPTSのオプションを変更している RC ファイルまたは環境変数 ( ) がある可能性はありますか? dieLevel私は個人的に使用したことはありませんdieLevelが、ゼロより大きい値に設定すると、スタックの巻き戻しを強制でき、「例外処理を真剣に受け止めるプログラムを絶望的に破壊する傾向がある」ようです。(ここから引用)。

于 2008-11-26T21:25:06.137 に答える