perl eval "...propagated" 记录在哪里
Posted
技术标签:
【中文标题】perl eval "...propagated" 记录在哪里【英文标题】:where is perl eval "...propagated" documented 【发布时间】:2021-09-25 11:11:25 【问题描述】:在以下代码中,eval
检查表达式是否有效。
它捕获一个异常,然后我的代码打印出异常,此时代码不会死掉。到目前为止,一切顺利。
但是当随后遇到die;
表达式时,异常文本再次打印出来,没有我的要求,添加了...propagated
消息,给出了行号die;
命令。
但在这一点上,异常文本是不恰当且令人困惑的。
似乎 perl 会保留 eval
错误消息或异常消息,直到我们到达 die;
。
在下面发布的代码下方是两种解决方法,其中任何一种都会使行为消失。
这种特殊行为记录在哪里?背后的想法是什么?
#!/usr/bin/perl
use strict; use warnings;
my $str=q/(d/;
my $rgx;
eval$rgx=qr/$str/;
if(length $@)
print join('', 'qr/', $str, '/ does not compile: ',"\n", $@, );
print "Got past eval. But next, at 'die;', it will print an error message that no longer pertains.\n";
die;
解决方法 (1)。给die;
一个非空字符串:
#!/usr/bin/perl
use strict; use warnings;
my $str=q/(d/;
my $rgx;
eval$rgx=qr/$str/;
if(length $@)
print join('', 'qr/', $str, '/ does not compile: ',"\n", $@, );
print "Got past eval. Next, the nonempty string in die ' '; flushes out the inappropriate exception message.\n";
die ' ';
解决方法 (2)。执行另一个没有发现语法错误的eval
:
#!/usr/bin/perl
use strict; use warnings;
my $str=q/(d/;
my $rgx;
eval$rgx=qr/$str/;
if(length $@)
print join('', 'qr/', $str, '/ does not compile: ',"\n", $@, );
print "got past eval\n";
$str=0;
eval$rgx=qr/$str/;
die;
【问题讨论】:
解决方法 #3:undef $@
在 if
块的末尾。这记录在perldoc -f die。
糟糕!对不起,我的句子彼此不相关。我的意思是回答“这是在哪里记录的?”您问题的一部分。
@JacobWegelin 我也认为没有真正的解决方法的理由;为什么不向die
提供消息?我总是想在那里发消息,不是吗?好吧,除非我想传播最后一个。在某些罕见的情况下(我无法轻易想象)你想要一个裸露的die
,那么是的,你必须明确地将它重置为空字符串或undef
。 (顺便说一句,我不是在批评这个问题——相反,这是一个很好的问题,经过深入研究和详细说明:)
[cont'd] 如果出于某种原因确实需要发出一个空的die
,我可能更喜欢用空字符串重置$@
(而不是@987654340 @),因为这是 eval
的行为——“如果没有发生错误,eval
将 $@
设置为空字符串”(在 $@
变量上说 perlvar
)。但这意味着您必须始终这样做,大概是在处理了eval
的错误消息之后,对于任何可能的后续裸die
。这将是一个令人不快的前景,我想说这实际上(在某种意义上)禁止空的die
,除了错误传播。
你希望通过eval
ing regexes 来完成什么而不让你的程序死掉?如果您尝试在 eval 语句中评估用户输入,这可能是一个严重的安全问题。
【参考方案1】:
我会说这是相当合乎逻辑的行为,die
不带参数使用。它应该做什么?
记录在die
如果 LIST 为空或为空字符串,并且
$@
已包含异常值(通常来自先前的eval
),则在附加"\t...propagated"
后会重复使用该值。这对于传播异常很有用:eval ... ; die unless $@ =~ /Expected exception/;
[...]
因此,在此设施中会混淆不带任何参数的不相关 die
。
【讨论】:
不需要变通方法。人们总是发出带有参数的die
,除非在这种行为派上用场时要传播先前的错误。【参考方案2】:
您需要向die
提供错误消息。如果您不这样做,这是documented 可能的结果之一。
如果 LIST 为空或为空字符串,并且
$@
已包含异常值(通常来自先前的eval
),则在附加"\t...propagated"
后会重复使用该值。这对于传播异常很有用:eval ... ; die unless $@ =~ /Expected exception/;
如果你想退出而不打印任何东西,你需要exit
。
exit( $! || ( $? >> 8 ) || 255 ); # The value that `die` uses.
但是,以下是更好且更惯用的解决方案:
my $rgx = eval qr/$str/
or die("Can't compile qr/$str/: $@");
【讨论】:
以上是关于perl eval "...propagated" 记录在哪里的主要内容,如果未能解决你的问题,请参考以下文章
Perl 模棱两可的命令行选项,以及带有 -i 的 eval 的安全隐患?
eval(data)和eval("("+data+")")的区别
Dash 和 C: eval "$(<cmdfile)" 和 system("eval \"\$(<cmdfile)\"") 给
<%# Eval("State") %> 或 <%# DataBinder.Eval(Container.DataItem, "state")