32

以前にこの質問をしたり、検索して他の人が尋ねたのを見たことがあります。なぜ「Subroutine mySub redefined at ../lib/Common.pm line x」という警告が表示されるのですか? そして、同じコードで sub を 2 回宣言した答えが常に得られます。このテスト パッケージを作成しました。

ファイル全体 ---------------

package MyCommonPkg;

use strict;

sub thisSubroutineIsNotDefinedAnywhereElse{
}

1;

ファイル全体 ---------------

そして、このパッケージを使用する他のパッケージを使用するperlスクリプトからこのパッケージを使用すると、次の警告が表示されます。

サブルーチン ThisSubroutineIsNotDefinedAnywhereElse が ../lib/MyCommonPkg.pm 行 19 で再定義されました。

このサブルーチンを他の場所で宣言していないことを約束します。これは循環参照が原因ですか?この警告の原因を追跡して修正するにはどうすればよいですか?

4

9 に答える 9

39

依存ループはありますか? Perl がスクリプトのコンパイルを開始し、次のような行に遭遇した場合:

use PackageA;

Perl はスクリプトのコンパイルを一時停止します。PackageA.pm を見つけてコンパイルを開始します。次のような行に遭遇した場合:

use PackageB;

Perl は PackageA のコンパイルを一時停止します。PackageB.pm を見つけてコンパイルを開始します。通常、これは正常に完了し、Perl は PackageA のコンパイルを完了するために戻り、それが正常に完了すると、スクリプトのコンパイルに戻り、正常に完了すると、コンパイルされたオペコードの実行を開始します。

ただし、 PackageB.pm に次の行が含まれている場合:

use PackageA;

Perl はすでに PackageA.pm を処理しているので、何もしないと思うかもしれませんが、問題はそれがまだ終わっていないことです。そのため、Perl は PackageB のコンパイルを一時停止し、PackageA.pm のコンパイルを最初からやり直します。これにより、PackageA のサブルーチンが再定義されているというメッセージが表示される可能性があります。

原則として、2 つのパッケージが互いに依存することはありません。ただし、3 番目のパッケージが原因であるため、ループを特定するのが難しい場合があります。

于 2010-08-07T05:37:35.700 に答える
23

異なるパッケージに同じ名前の 2 つのサブルーチンがある場合、この警告 (警告が有効になっている場合) は「Subroutine new redefined....」と表示されます。単純な理由 (Grant McLean が言ったことに非常に近いが、正確ではない) は、パッケージをコンパイル フェーズをスキップさせてから、require にする必要があるためです。このようにして、Perl 名前空間マネージャーは、コンパイル時に同じ名前の競合するシンボルを検出しません。また、モジュールにエラーがなければ、その後も問題なく動作します。

必ず実装してください

モジュールが必要です。

ではなくステートメント

モジュールを使用します。

この警告が再び表示されることはありません。

于 2012-08-10T22:58:31.623 に答える
8

大文字と小文字を区別しないファイルシステム (Windows、そして多くの場合 OSX) を使用しているシステムを使用していてuse Common、あるファイルとuse common別のファイルでこれを行うと、このような問題が発生する可能性があります。

于 2010-08-07T00:33:41.117 に答える
7

これは、循環依存関係によって引き起こされる問題のように思えます。追跡する方法は次のとおりです。問題のクラスが次のようになっている場合:

package AlientPlanet;
use Dinosaurs;
sub has_dinosaurs {...}
1;

次に、例を次のように変更します。

package AlienPlanet;
sub has_dinosaurs {...}     # <-- swap
use Dinosaurs;              # <-- swap
1;

次のようにCarp::Alwaysでコードをコンパイルします。

⚡ perl -MCarp::Always -c lib/AlienPlanet.pm                                                                                                            
Subroutine has_dinosaurs redefined at lib/AlienPlanet.pm line 4.
    require AlienPlanet.pm called at lib/Dinosaurs.pm line 4
    Dinosaurs::BEGIN() called at lib/AlienPlanet.pm line 4
    eval {...} called at lib/AlienPlanet.pm line 4
    require Dinosaurs.pm called at lib/AlienPlanet.pm line 5
    AlienPlanet::BEGIN() called at lib/AlienPlanet.pm line 4
    eval {...} called at lib/AlienPlanet.pm line 4
lib/AlienPlanet.pm syntax OK

スタック トレースが作成されたので、ループの場所を確認できます。手っ取り早い解決策は、Dinosaurs.pm でClass::Loadを使用することです。

より詳細な説明については、私のブログ投稿を試してください。

于 2013-01-20T21:54:04.577 に答える
2

ひょっとして、これを Web サーバー上で cgi スクリプトとして実行しているのでしょうか?

この警告を回避するには、Web サーバーを再起動する必要があります。

于 2011-02-27T15:43:09.073 に答える
0

パッケージ名は「package Common.pm」にしてみました。コンパイラでエラーが発生しました。とても親切ですよね?Perl のどのバージョンを使用していますか? 5.10.0 と 5.12.1 で試してみました。

コンパイルできたとしても、.pm ファイルを削除することをお勧めします。例えば;

ファイル: some_package.pm;

package some_package;
use strict;

sub yadayadayada { ... }

1;
于 2010-08-07T01:51:00.413 に答える
0

モジュールの最後にある次の行を忘れていないことを確認してください。

1;

ここのいくつかの例に含まれていることは知っていますが、見落としやすいので言及し、私の場合はエラーの唯一の原因であることが判明しました!

于 2012-05-01T23:16:52.230 に答える