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,除了错误传播。 你希望通过evaling 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 的安全隐患?

Perl eval EXPR 用单引号或双引号括起来

eval(data)和eval("("+data+")")的区别

Dash 和 C: eval "$(<cmdfile)" 和 system("eval \"\$(<cmdfile)\"") 给

<%# Eval("State") %> 或 <%# DataBinder.Eval(Container.DataItem, "state")

eval 啥意思?