如何确定perl警告的位置-插入后在哈希上使用each()
我有一个相当大的perl程序,用PAR::Packer打包成一个可执行文件。它使用了相当多的模块 通常,当perl给我一个警告时,比如使用未定义的值,它会打印错误的位置,然后很容易深入并调试它 然而,我现在面临一个错误(我想是在5.22中引入的),当这种情况发生时,我得不到任何位置:如何确定perl警告的位置-插入后在哈希上使用each(),perl,Perl,我有一个相当大的perl程序,用PAR::Packer打包成一个可执行文件。它使用了相当多的模块 通常,当perl给我一个警告时,比如使用未定义的值,它会打印错误的位置,然后很容易深入并调试它 然而,我现在面临一个错误(我想是在5.22中引入的),当这种情况发生时,我得不到任何位置: 插入后对哈希使用each()而不重置哈希迭代器会导致未定义的行为,Perl解释器:0xa94010 我尝试设置use warnings FATAL=>'all',但没有任何变化,程序不会消亡 也许它来自一个模块?还
插入后对哈希使用each()而不重置哈希迭代器会导致未定义的行为,Perl解释器:0xa94010
我尝试设置use warnings FATAL=>'all'代码>,但没有任何变化,程序不会消亡
也许它来自一个模块?还有什么方法可以确定警告的位置呢?我想您可以使用诊断或splain。我已经使用了诊断,如果我们无法跟踪产生警告的位置,它会有所帮助
您只需将行置于使用诊断代码>在您的代码中就是这样。您可以在PerlMaven站点找到对此的详细解释-
谢谢。pragma从一组给定的类别中发出法律代码警告。虽然FATAL
会将它们更改为致命错误,但它不会更改warn
的工作方式。由于不知道这是如何发出的,因此重写\uuuu WARN\uuuu
钩子可能会有所帮助
local $SIG{__WARN__} = \&Carp::confess; # or just die
或者你也可以只在这一次删除local
另一件要尝试的事情是覆盖
这也会影响模块,如果在模块之前的开始
中设置了警告
信号,也会影响模块
请注意,它可以实现这一点,甚至更多。此外,它通常在运行程序时被激活,使用-MCarp::Always
。谢谢你的澄清
看和,还有这个
最后,您有多少次对的调用?全部检查一下
注释中解释了打印来自通过调试器找到的XS,但仍然不知道是什么代码触发了这一点。然后尝试将流绑定到一个类,在该类中相关文本上触发跟踪。最简单的例子
TraceError.pm
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;
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;
更改为注释掉的if
行,以便扫描打印的错误消息文本。下面剩下的只是一个测试。在您的代码中,您需要从main.pl
开始的前两行,以使用该类并将流(filehandle)绑定到它,然后所有打印(到STDERR
)通过上面的PRINT
进行
main.pl
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
};
Pack.pm
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;
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;
输出
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
在包中,发出\u警告(跟踪,调用\u以获取\u err()。下午12点12分。
下午12点12分。
Pack::在main.pl第12行调用发出警告('Pack=HASH(0x7016e8)','TRACE call_for_err()')
main::在main.pl第8行调用\u err('Pack=HASH(0x7016e8)')时调用\u
tie
-ing类的编写应该更加精巧,首先是为了获取参数(要搜索的文本、要打印的流或句柄)。请参阅和,讨论,帖子等,尤其是骆驼(第三版)中的“捆绑文件句柄”一章
你应该有一个行号
>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::总是将其扩展到堆栈跟踪中
>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
运行非打包版本?我刚刚测试了非打包版本,它也不会打印出行。所做的只是获取警告并在perldoc perldiag
的源代码中查找它,然后显示该文本。这无助于在perl源代码和模块中找到警告的来源。-MCarp::Always
基本上就是这样做的,还有更多:)@ikegami我知道了,谢谢!源代码非常漂亮,有几十行:)因此-MCarp::Always
也没有帮助。仍然没有位置信息。至于每次调用
我都会查看代码;没有每个
在所有的foreach
看起来都没有可疑之处。我倾向于一些模块/XS代码(特别是因为通常情况下,如果它发生在我的代码中,我会得到正确的位置)。@VitSpinka OK。您是否尝试过使用CORE::GLOBAL::warn
?这会改变每个warn
的工作方式,而Carp::Always
会做一些不同的事情。以防万一--这是在STDERR
还是STDOUT
上出现的?(如果您将输出重定向到一个文件,它是否会在控制台上打印?)我将研究更多的方法。@VitSpinka源代码可能正在使用CORE::warn
,这正是阻止这些游戏的方法,在这种情况下,这不会有帮助。或者,更有可能的是,在发出warn
后,线路信息以其他方式被剥离。