0

情况是我正在sub尝试使用调用者的$aand $b,类似于什么sort。大多数时候它可以工作,但是在运行单元测试时,我注意到在一种情况下,在一个包内,它不起作用。我caller用来获取调用者的包,然后设置它们$a$b如下面的简化演示所示。只需在我发现这个的包中调用这个函数,就会出现这个问题。whatever

sub whatever {         # defined in main package
  my $pkg = caller;
  no strict 'refs';
  ${"${pkg}::a"} = "";
  ${"${pkg}::b"} = "";
}

我试图创建一个最小的包/类来重现问题,但在这种情况下不会出现问题,但我还是在下面发布了我的尝试作为一般上下文的指示:

package WhateverClass {
    sub new {
        my ($class, $something, $something2) = @_;
        my $this = {};
        bless $this, $class;
        $this->{something_} = $something;
        $this->{something2_} = $something2;
        return $this;
    }
    sub test { # bug reproduction
        main::whatever();
    }
}

my $obj = WhateverClass->new(1.0, 2.0);
$obj->test;

错误信息是,

Error: "Cannot copy to ARRAY in scalar assignment"

它是由确切的行触发的:

${"${pkg}::a"} = "";

将其缩小到这个“随便”函数后,我尝试在该赋值的右侧放置各种东西,包括 arrayrefs、数组、如图所示的字符串、数字以及 undef。它接受的只有 undef、整数值和浮点值。它不接受 arrayrefs、hashrefs 或字符串。在我的例子中,在暴露这个问题的原始代码中,传递的东西是对象引用或祝福 hashrefs,如果任何 hashref 或 arrayref 分配失败,这些分配就会失败,正如你所期望的那样。

更奇怪的是,在 Perl 调试器下问题不会发生,但如果我正常运行它就会发生。

谷歌搜索这个结果没有匹配这个确切的错误,甚至几乎没有。所以第一个问题是这个错误消息是什么意思?第二个问题显然是如何前进。

我在 Linux 上使用 Perl 5.20.3,但我也在 Windows 机器上尝试了最新的 5.22 并看到了相同的行为。

4

1 回答 1

0

我发现对我的修复与这样一个事实有关,即在使用此代码时看到任何问题的唯一位置的包在其生命周期中的某个时间点出现在问题出现之前List::MoreUtils pairwise。一些但不是全部的问题行为在调试器中是可重现的,我追踪了“错误”行为的开始位置,并且是在调用pairwise. 我将这个调用切换为使用我自己的一个例程,该例程基本上做同样的事情,问题完全消失了(感谢上帝)。这是一个相当令人不安的问题。正如@ikegami 所指出的,“错误的 XS 代码”可能是问题所在,而我的例程是纯 Perl,没有任何 XS 代码。

于 2016-03-07T05:13:01.930 回答