【问题标题】:Unknown cause of crash in lambda function using Armadillo types使用犰狳类型的 lambda 函数崩溃的未知原因
【发布时间】:2015-02-10 15:47:06
【问题描述】:

编辑:更新代码使两个函数更加相似

我在 lambda 函数中使用犰狳类型时遇到问题,当尝试读取无效内存位置时会导致崩溃。如果我将相同的表达式移到普通函数中,一切都会顺利进行。

所以,简单的工作示例:

#define ARMA_USE_CXX11
#include <armadillo>

using namespace arma;

rowvec2 funcLambda( double value, const rowvec2 &vA, const rowvec2 &vB, const double &const1, const double &const2 ){
    return min( vA * const1, vB * const2 );
}

int main( void ){

    rowvec2 vA = {.12, .44};
    rowvec2 vB = {2, 2};
    auto const1 = double( 1.2 );
    auto const2 = 3.1;
    auto fLambda = [&]( double value ){ return min( vA * const1, vB * const2 );};
    rowvec2 z = rowvec2({0.0, 0.0});

    // This works fine
    z = funcLambda( 100, vA, vB, const1, const2 );
    // This crashes
    z = fLambda( 100 );

    return 1;
}

这个例子在note所在的地方崩溃,有没有“using namespace arma;”包括行,有和没有#define ARMA_USE_CXX11,并使用32位和64位内存寻址。

我不知道是我在 lambda 函数中做错了什么,还是犰狳导致了问题。如果我删除等式的一部分(例如标量的乘法),它将正常工作。

感谢任何帮助。

谢谢

亨里克

【问题讨论】:

  • 我看到了两个不同之处。首先,lambda 中的引用是const&amp;,而在函数中它们是&amp;。其次,funcLambda 进行构造,而fLambda 进行赋值。如果消除这些差异,行为会改变吗?
  • @Yakk:我在函数中更改了对 const& 的引用,并使两个函数调用都进行了赋值。虽然结果相同。原始问题中的代码已更新。

标签: c++ lambda crash armadillo


【解决方案1】:

犰狳大量使用惰性求值,并且有大量中间结果通过引用保存其他生命周期有限的中间结果1。这里要咬你的是min 的返回值,并且你试图在得到它时返回它。

如果你像这样改变你的 lambda:

auto fLambda = [&]( double value ) -> rowvec2 { return min( vA * const1, vB * const2 ); };

也就是说,如果您明确指定它返回一个rowvec2 而不是您从min 获得的Glue&lt;eOp&lt;rowvector2, eop_scalar_times&gt;, eOp&lt;rowvector2, eop_scalar_times&gt;, glue_min&gt;,那么问题应该会消失,因为在函数返回之前中间结果已转换为有形的东西。

1 是的,真的。您可以在/usr/include/armadillo_bits/Glue_bones.hpp 中看到这一点。它们根本不适合存储。

【讨论】:

  • 加 1:啊,“operator auto”/依赖引用生命周期延长问题。 (出于这个原因,有一些建议可以改变 rype 从中推断出的值类型——我称之为operator auto
  • 是否有一个store 函数我们可以用于此目的?还是可以从表达式模板推导出预期的存储类型(所以我们可以写一个)?
  • @Yakk 嗯...推断存储类型应该是可能的(并且不是非常困难),但我认为目前在犰狳中没有这些设施。我的意思是,eOp 的存储类型是它的参数的存储类型,矩阵向量乘法的存储类型是一个向量——实现它会是一些工作,因为它会触及每一个操作,但它不会不是火箭科学。
  • 还有.eval()函数
  • @Yakk 啊,我的立场是正确的。设施在那里,然后可以用decltype推断类型。
猜你喜欢
  • 1970-01-01
  • 2017-06-24
  • 2013-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
  • 2020-04-29
相关资源
最近更新 更多