我有一个非常大的perl程序,用PAR :: Packer打包到一个可执行文件。它使用了相当多的模块。
通常,当perl给我一个警告时,比如使用未定义的值,它会打印出错误的位置,然后很容易深入调试它。
然而,我现在面临一个错误(我认为在5.22中引入),当发生这种情况时,我没有位置:
Use of each() on hash after insertion without resetting hash iterator results in undefined behaviour, Perl interpreter: 0xa94010
我尝试设置use warnings FATAL=>'all';
,但没有任何变化,程序也不会死。
也许它来自一个模块?我怎样才能确定警告的位置?
答案 0 :(得分:2)
warnings pragma从一组给定的类别中发出合法代码的警告。虽然FATAL
会将其更改为致命错误,但它不会更改warn
的工作方式。由于不知道这是如何发出的,因此覆盖__WARN__
挂钩可能会有所帮助
local $SIG{__WARN__} = \&Carp::confess; # or just die
或者您也可以这一次放弃local
。
要尝试的另一件事是覆盖CORE::GLOBAL::warn
BEGIN { *CORE::GLOBAL::warn = sub { die } } # before use Module;
这也会影响模块,如果__WARN__
信号在模块之前设置,也会影响模块。
请注意Carp::Always完成此操作,等等。此外,它通常仅在运行程序时使用BEGIN
激活。感谢ikegami澄清。
请参阅warn和%SIG hash in perlvar以及此Effective Perler article。
最后,您有多少次拨打-MCarp::Always
?检查一下。
在评论中解释说,打印来自XS,通过调试器找到,但仍然不知道是什么代码触发了这个。然后尝试each
- 将流转换为类,其中在相关文本上触发跟踪。最小的例子
<强> TraceError.pm 强>
tie
更改为已注释的package TraceError;
use warnings;
use strict;
use Carp qw(longmess confess);
sub TIEHANDLE { bless {} }
sub PRINT {
my $self = shift;
my $prn = join '', @_;
# print "STDERR: $prn"; # TEST
print @_; # or print STDERR @_;
# if ($prn =~ /\QUse of each() on hash after insertion/) # in your code
if ($prn =~ /TRACE/) { # test
print longmess(@_);
}
}
1;
行,以便扫描错误消息文本的打印件。下面的其余部分只是对此的测试。在您的代码中,您需要前两行if
,main.pl
此类和use
流(文件句柄)到它,然后所有打印(到tie
)去通过上面的STDERR
。
<强> main.pl 强>
PRINT
<强> Pack.pm 强>
use TraceError;
tie *STDERR,'TraceError';
use warnings;
use strict;
use Pack qw(issue_warn);
call_for_err(Pack->new);
sub call_for_err {
my ($pck) = @_;
$pck->issue_warn("TRACE call_for_err()"); # should catch this print
$pck->issue_warn("from call_for_err()"); # but not this
};
输出
In Pack, issue_warn(TRACE, call_for_err()). at Pack.pm line 12. at Pack.pm line 12. Pack::issue_warn('Pack=HASH(0x7016e8)', 'TRACE call_for_err()') called at main.pl line 12 main::call_for_err('Pack=HASH(0x7016e8)') called at main.pl line 8
package Pack;
use warnings;
use strict;
use Exporter qw(import);
our @EXPORT_OK = qw(issue_warn);
sub new { bless {}, $_[0] }
sub issue_warn {
my $self = shift;
warn "In ", __PACKAGE__, ", issue_warn(@_).";
}
1;
- ing类应该写得更好,首先要采用参数(文本搜索,流或句柄打印到)。请参阅perltie和Tie::Handle,关于perlmonks的讨论,关于SO的帖子,例如this one,以及最重要的章节&#34; 绑定文件句柄 &#34;在Camel(第3版)。
答案 1 :(得分:1)
use strict;
use warnings;
sub g {
my %h = ( a => 4, b => 5 );
my $done = 0;
while (my ($k, $v) = each(%h)) {
print("$k\n");
$h{c} = 6 if !$done++;
}
}
sub f {
g();
}
f();
你应该有一个行号!
>perl a.pl
a
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior, Perl interpreter: 0xe688d8 at a.pl line 8.
b
c
Carp :: Always会将其扩展到堆栈跟踪中。
>perl -MCarp::Always a.pl
a
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior, Perl interpreter: 0x1e88d8 at a.pl line 8.
main::g() called at a.pl line 15
main::f() called at a.pl line 18
c
b
答案 2 :(得分:-1)
我认为你可以使用诊断或splain。我已经使用了诊断功能,如果我们无法跟踪生成警告的位置,它会有所帮助。
您只需将代码行use diagnostics;
放在代码中即可。您可以在Perl Maven网站上找到详细的解释 - Link。
感谢。