我之前已经问过这个问题或者搜查过其他人问过 - 为什么我收到警告" 子程序mySub重新定义在../lib/Common.pm第x行 "?并且你总是得到你在同一个代码中声明sub两次的答案.我创建了这个测试包:
整个文件---------------
package MyCommonPkg;
use strict;
sub thisSubroutineIsNotDefinedAnywhereElse{
}
1;
Run Code Online (Sandbox Code Playgroud)
整个文件---------------
我使用perl脚本使用这个包,它使用其他包,也使用这个包,我得到警告:
子程序ThisSubroutineIsNotDefinedAnywhereElse在../lib/MyCommonPkg.pm第19行重新定义.
我保证我没有在其他地方声明这个子.这是由循环引用引起的吗?如何跟踪此警告的原因并进行修复?
Gra*_*ean 34
你有依赖循环吗?如果Perl开始编译脚本并遇到如下所示的行:
use PackageA;
Run Code Online (Sandbox Code Playgroud)
Perl暂停编写脚本; 找到PackageA.pm并开始编译它.如果遇到这样的一行:
use PackageB;
Run Code Online (Sandbox Code Playgroud)
Perl暂停编译PackageA; 找到PackageB.pm并开始编译它.通常,这将成功完成,Perl将返回完成编译PackageA,当成功完成时,它将返回编译脚本,当成功完成时,它将开始执行已编译的操作码.
但是,如果PackageB.pm包含以下行:
use PackageA;
Run Code Online (Sandbox Code Playgroud)
您可能期望它不会做任何事情,因为Perl已经处理了PackageA.pm,但问题是它还没有完成.所以Perl将暂停PackageB的编译并从头开始再次开始编译PackageA.pm.这可能会触发您在重新定义PackageA中的子例程时看到的消息.
作为一般规则,两个包不应相互依赖.然而,有时循环更难定位,因为它是由第三个包引起的.
小智 24
如果在不同的包中有两个具有相同名称的子例程,则应该看到此警告(启用警告时)为"Subroutine new redefined ....".一个简单的原因(非常接近Grant McLean所说的,但仍然不完全正确)是你必须让你的包跳过编译阶段然后再需要.这样,Perl命名空间管理器在编译时将找不到任何具有相同名称的冲突符号,如果模块没有任何错误,那么它们之后也会正常工作.
只要确保你实施
需要模块;
声明而不是
使用模块;
你不应该再看到这个警告.
如果您使用的是具有不区分大小写的文件系统(Windows,通常是OSX)的系统,并且您use Common在一个文件和use common另一个文件中执行,则可能会导致此类问题.
这听起来像是由循环依赖引起的问题。这是跟踪它的方法。如果您的问题类如下所示:
package AlientPlanet;
use Dinosaurs;
sub has_dinosaurs {...}
1;
Run Code Online (Sandbox Code Playgroud)
然后将您的示例更改为如下所示:
package AlienPlanet;
sub has_dinosaurs {...} # <-- swap
use Dinosaurs; # <-- swap
1;
Run Code Online (Sandbox Code Playgroud)
现在用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
Run Code Online (Sandbox Code Playgroud)
现在你有了一个堆栈跟踪,你可以看到循环在哪里。快速而肮脏的解决方案是在 Dinosaurs.pm 中使用Class::Load。
有关更详细的解释,请尝试我的博客文章。
| 归档时间: |
|
| 查看次数: |
27939 次 |
| 最近记录: |