2015-02-10 83 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