【问题标题】:Perl : empty variable while using eval in a threadPerl:在线程中使用 eval 时为空变量
【发布时间】:2014-11-24 21:06:34
【问题描述】:

我在将项目从 perl 5.8.8 更新到 perl 5.18.2 时遇到问题。
我已将问题简化为以下示例:

use threads;

my $key = "abcdef";

print "test1 key = $key.\n";

my $thr = threads->create(sub {
    eval "print \"test2 key = \$key.\n\";";
}); 

$thr->join();

在 perl 5.8.8 中,这给出了正确的输出:

test1 key = abcdef.
test2 key = abcdef.

但是对于 perl 5.18.2,我有:

test1 key = abcdef.
test2 key = .

我尝试了其他 perl 版本,问题似乎出现在 5.14.0 版本中。 我正在寻找解决此问题的最佳方法,以及有关此 perl 行为修改的解释。

我找到了一些替代品,但它们似乎都不适合我:

  • 使用“我们的 $key”而不是“我的 $key”;但这会使变量“更加公开”
  • 添加“我的 $toto = $key;”在 eval 行之前(同时在 eval 行中仍然使用 $key);事实上,在 eval 行之前用 $key 做一些事情(打印、做作、使用......)似乎可以解决问题。但是添加的行对功能没有用。

在 eval 命令中使用 $key 而不是 \$key 对我来说不是一个解决方案,因为在实际程序中我将处理更复杂的结构。

【问题讨论】:

    标签: multithreading perl eval


    【解决方案1】:

    问题与线程无关。查看类似的PerlMonks 线程。要创建闭包,编译器需要知道将使用的变量。您可以只提及要关闭的 sub 中的变量:

    my $thr = threads->create(sub {
        $key;  # Create a closure.
        eval "print \"test2 key = \$key.\n\";";
    }); 
    

    要查看类似的非线程情况,只需创建一个作用域:

    my $sub = do {
        my $key = "abcdef";
        print "test1 key = $key.\n";
        sub {
            $key; # <-- Comment this line to get no value.
            eval "print \"test2 key = \$key.\n\";";
        }
    };
    
    $sub->();
    

    【讨论】:

    • 感谢您的回答!你知道为什么它使用 perl 5.8.8 而不在变量中添加提及吗?
    • 您想知道为什么 5.8.8 捕获了它不需要的变量吗?因为它就是这样编码的。
    • @ikegami:听起来很熟悉:)
    • 这是很多人(包括我自己)发现的错误,最终在 5.14 中修复。它导致闭包捕获过多的外部范围,这有时会对引用计数和内存回收产生不良后果。
    【解决方案2】:

    Perl 有两个名为 eval 的函数。

    • eval EXPR 解析并执行 Perl 代码。

    • eval BLOCK 是一个异常陷阱。这在其他语言中通常称为try

    使用正确的函数将解决您的问题,因为它不会尝试使用不再存在的变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      • 2015-04-27
      • 1970-01-01
      • 2010-12-05
      • 1970-01-01
      相关资源
      最近更新 更多