2017-08-01 9 views
0

次のコードはセグメンテーションフォールトを示しています。それをデバッグした後、関数ではなくラムダをautoと宣言することで問題を解決できることがわかりました。それはなぜですか?std :: functionとしてラムダを格納する際のセグメンテーションエラー

#include <functional> 
#include <iostream> 
#include <vector> 

typedef std::vector<double> Vec; 
typedef std::function<const Vec&(Vec)> Function; 


int main() 
{ 
    //Function func = [](const Vec& a)->Vec /*this give me segfault*/ 
    auto func = [](const Vec& a)->Vec /*this work just fine??*/ 
     { 
       Vec b(2); 
       b[0] = a[0] + a[1]; 
       b[1] = a[0] - a[0]; 
       return b; 
     }; 
    Vec b = func(Vec{1,2}); 
    std::cout << b[0] << " " << b[1] << "\n"; 
    return 0; 
} 

私は は、いくつかの他のクラスには、このラムダ式を渡すしたいと思いますので、私は機能としてそれを宣言することができればそれは素晴らしいことです。 FUNCは関数として宣言されたときに、私が持っている

エラーは次のとおりです。

プログラムは、信号SIGSEGV、セグメンテーションフォールトを受けました。 /usr/include/c++/5/bits/stl_vector.h:655のstd :: vector> :: size(this = 0x0)の0x0000000000401896が返されます。{return size_type(this - > _ M_impl._M_finish - this - > _ M_impl。 _M_start); }
(GDB)バックトレース
#0 0x0000000000401896 STDで::ベクトル> ::サイズ(これは0x0の=)/usr/include/c++/5/bits/stl_vector.h:655
#1 0x00000000004015aa中で/usr/include/c++/5/bits/store/vector.h:320の の
test.cxxのmain()の#2 0x0000000000400d12:18

のstd :: vector> :: vector(this = 0x7fffffffdc50、__x =)

答えて

6

const Vec&(Vec)は、(Vec) -> const Vec&のようなラムダに相当します。 (const Vec&) -> Vecを渡します。

std::functionは、有効な変換を含む呼び出しシーケンスのために受け入れます(const参照が必要な関数に値を渡すことができます)。

セグメンテーションフォルトは、std::functionoperator()のconst参照にバインドされているラムダ(一時的な)の戻り値に固有の未定義の動作です。その参照はstd::functionの外部に返されており、直ちに参照が宙づりになります。

1

関数の種類に注意する必要があります。正しい関数型を使用するとうまくいくはずです。

typedef std::function<Vec(const Vec&)> Function; 

おそらく、オブジェクトラッパーの数や従来の関数の数が減るにつれて、問題はより明確になります。

それはあなたがオブジェクトを通して間接を削除したら、これで、つまるところ何:

// const Vec& -> Vec 
std::vector<double> the_lambda(const std::vector<double>& x) 
{ 
    return x; 
} 

// Vec -> const Vec& 
const std::vector<double>& the_function(std::vector<double> x) 
{ 
    return the_lambda(x); 
} 


int main() 
{ 
    std::vector<double> v = {1, 2}; 
    std::vector<double> lv = the_lambda(v); // OK. 
    std::vector<double> fv = the_function(v); // Undefined. 
} 

これはコンパイルが、the_functionがで起こるまさにである、一時的に参照を返すことを警告++グラムstd::function(ただし、コンパイラのヒントはあまりありません)。

(私はstd::functionに返された値のこの変換を可能にすることが間違いであることをかなり確信している。あなたは、関数ポインタを使用していた、とC++がよりより安全であると考えられる場合にはそれで逃げるませんC、それ以下)

関連する問題