2015-02-10 82 views
2

编辑:更新的代码,以使两个功能更类似于不明原因使用犰狳种类

我有一个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; 
} 

这个例子崩溃,其中值得注意的是,有和没有“使用命名空间ARMA;”包括带有和不带#define ARMA_USE_CXX11,并使用32位和64位存储器地址。

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

任何帮助表示赞赏。

由于

的Henrik

+1

我看到两个区别。首先,lambda中的引用是'const&',而在函数中它们是'&'。其次,'funcLambda'构建,而'fLambda'确实分配。如果消除这些差异,行为是否会改变? – Yakk 2015-02-10 15:57:02

+0

@Yakk:我改变了对函数中const&的引用,并使得两个函数调用都做了赋值。尽管如此。代码在原始问题中更新。 – Henrik 2015-02-10 16:06:40

回答

3

犰狳大量使用惰性计算的,并具有大量的由参考保持其它中间体具有有限寿命的中间结果。在这里来咬你的那个人是min的返回值,并且你尝试返回它。

如果您改变拉姆达这样的:

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

也就是说,如果你明确指定,它返回一个rowvec2,而不是你从min得到Glue<eOp<rowvector2, eop_scalar_times>, eOp<rowvector2, eop_scalar_times>, glue_min>,问题应该消失,因为中间结果是在函数返回之前转换为有形的东西。

是的,真的。你可以在/usr/include/armadillo_bits/Glue_bones.hpp看到这个。它们根本不是要存储的。

+0

加1:啊,“'操作符自动'”/依赖引用生存期延长问题。 (已经有一些建议来调整rype更改从中推导出什么样的值类型 - 因为这个原因 - 我将其称为'operator auto') – Yakk 2015-02-10 16:32:11

+0

我们可以使用一个'store'函数来实现这个目的吗?或者是从表达式模板中推导出的预期存储类型(所以我们可以写一个)? – Yakk 2015-02-10 16:34:23

+0

@Yakk嗯......应该有可能(并且非常困难)推断出存储类型,但我认为目前这些设施并不在Armadillo中。我的意思是,'eOp'的存储类型是它的参数的存储类型,矩阵向量乘法的存储类型是一个向量 - 实现它会是一些工作,因为它会触及每一个操作,但它不会'不是火箭科学。 – Wintermute 2015-02-10 16:45:56