为什么传递特征表达式的临时表会导致访问未定义的内存?

时间:2014-09-10 05:14:14

标签: c++ eigen

在尝试追踪错误时,我已经能够提出以下简单程序来说明问题:

#include <iostream>
#include <Eigen/Dense>

using Mat = Eigen::Matrix<double, 1, 1, Eigen::AutoAlign>;

template <typename Derived>
auto Modify(const Eigen::DenseBase<Derived>& value)
    -> decltype(2*value.derived().array())
{
    return 2*value.derived().array();
}

Mat Make()
{
    Mat mat;
    mat << 2;
    return mat;
}

int main()
{
    auto mat = Make();

    std::cout
        << "first: " << Modify(mat) << std::endl
        << "second: " << Modify(Modify(mat));

    return 0;
}

该程序的输出是:

first: 4
second: 3.95253e-323

在valgrind下运行生成的代码会产生Uninitialised value was created by a stack allocation错误。

上述代码有什么问题吗?由于原始mat矩阵在评估矩阵的范围内,为什么我正在创建Eigen::DenseBase表达式的临时值?

我尝试使用Eigen 3.2.1以及Eigen 3.2.2进行编译并得到相同的结果。

2 个答案:

答案 0 :(得分:3)

value.derived().array()返回一个临时的ArrayWrapper对象。 2 * value.derived().array()构造一个表达式对象,该对象存储对该ArrayWrapper的引用,但之后会立即销毁该临时ArrayWrapper。因此,从Modify返回的表达式对象包含悬空引用。

答案 1 :(得分:3)

T.C.的答案是正确的但是这种行为是无意的,因为轻量级表达式应该被值嵌套,而不是通过引用嵌套。在ArrayWrapper中存在一些缺点,在某些情况下它会被引用嵌套。现在,3.2和默认分支都已修复此问题。所以你的例子现在工作正常。