2015-06-25 24 views
0

我試圖構建一個lambda包含一些前/後操作的輸入函數。變量在調用lambda之前被破壞

  • 我的代碼工作正常,並且如果我嘗試包裝常規函數/ lambda,則前/後操作會正確調用。但是,當我嘗試將我的裝飾lambda應用於它之前生成的函數時,我的程序在抱怨內部函數在某個時候被釋放(這由valgrind確認)後崩潰。

令我百思不解的是,碰撞依賴於編譯:代碼工作完全正常與Xcode 6 clang(基於clang-3.6),但使用clang++-3.6g++4.8.4在Linux上崩潰。

我做了一個小程序,再現行爲:

#include <iostream> 
#include <string> 
#include <functional> 

using namespace std; 

typedef function<void(void)> NestedFn; 

int main() 
{ 
    // Create a cfunction 
    auto lambdaFactory = [&](string title, NestedFn nestedFunc) 
    { 
     // title is copied to the new lambda 
     return [&, title]() { 
      cerr << "------------ START -----------" << endl; 
      cerr << "Inside: " << title << endl; 
      nestedFunc(); 
      cerr << "------------- END ------------" << endl; 
     }; 
    } 

    auto l1 = lambdaFactory("1", []() { cerr << "\tNest (1)" << endl; }); 
    auto l2 = lambdaFactory("2", []() { cerr << "\tNest (2)" << endl; }); 

    l1(); // Works ok, displays, START, 1, END 
    l2(); // Same here 

    auto dobble = lambdaFactory("Dobble", l1); 
    dobble(); // Display START, Inside Dobble, START, 
       // then crashes when trying to execute nestedFunc(), ie l1() 
} 

我是怎麼弄錯的可變範圍管理?這個程序不是使用蘋果的LLVM崩潰嗎?

編輯

爲了記錄在案,這裏是T.C.建議修正後的正確lambdaFactory

auto lambdaFactory = [&](string title, NestedFn nestedFunc) 
{ 
    return [&, title, nestedFunc]() { 
     cerr << "------------ START -----------" << endl; 
     cerr << "Inside: " << title << endl; 
     nestedFunc(); 
     cerr << "------------- END ------------" << endl; 
    }; 
}; 
+2

的問題是,'lambdaFactory'的參數是按值傳遞,因此如果要返回lambda,則必須通過值捕獲它們。否則,你會有一個懸而未決的引用,因爲函數參數一旦返回就會超出範圍。 –

回答

2

通過向lambdaFactory一個調用返回的拉姆達捕捉參照nestedFunc,但nestedFunc是一個按值傳遞的函數參數,所以只要對lambdaFactory的調用返回就會超出範圍,從而導致引用不穩定。

是否有任何理由讓這個程序不崩潰使用蘋果的LLVM?

未定義的行爲是未定義的。您還可能使用兩個不同的標準庫的實現(libc中++在Mac /的libstdC++在Linux上),所以有一切是如何等佈局可能差異

+0

謝謝!我將'lambdaFactory'中的行從'return [&,title](){'改爲'return [&,title,nestedFunc](){'並且它可以工作。我沒有意識到''nestedFunc'被認爲是'lambdaFactory'中的一個值。 – sansuiso