Multithreading Perl:在线程中使用eval时为空变量
将项目从perl 5.8.8更新到perl 5.18.2时,我遇到了一个问题。Multithreading Perl:在线程中使用eval时为空变量,multithreading,perl,eval,Multithreading,Perl,Eval,将项目从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中,这提供了正确的输出: test
我已将问题简化为以下示例:
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 beaviour修改的解释
我已经找到了一些替代方案,但没有一个适合我:
- 使用“我们的$key”而不是“我的$key”;但这使得变量“更公开”
- 在评估行之前添加“my$toto=$key;”(在评估行中仍然使用$key);事实上,在eval行之前使用$key做一些事情(打印、做作、使用…)似乎可以解决问题。但是添加的行对于函数是无用的
在eval命令中使用$key而不是\$key对我来说不是一个解决方案,因为在实际的程序中,我将处理更复杂的结构。这个问题与线程无关。看到一条类似的线。要创建闭包,编译器需要知道将使用的变量。您可以在要关闭的子项中提及变量:
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->();
my$sub=do{
my$key=“abcdef”;
打印“test1 key=$key.\n”;
潜艇{
$key;#();
Perl有两个名为eval
的函数
解析并执行Perl代码eval EXPR
是一个异常陷阱。这在其他语言中通常称为eval BLOCK
try
使用适当的函数将解决您的问题,因为它不会尝试使用不再存在的变量。谢谢您的回答!您知道为什么它在使用perl 5.8.8时没有添加对变量的提及吗?您想知道为什么5.8.8捕获了它不需要的变量?因为它就是这样编码的。@ikegami:听起来不错熟悉:)这是包括我在内的许多人发现的一个bug,最终在5.14中得到了修复。它导致闭包捕获了太多的外部范围,这有时会对引用计数和内存回收造成不良后果。