将lambda存储为std :: function时出现分段错误

时间:2017-08-01 07:18:09

标签: c++ lambda std-function

以下代码给出了分段错误。调试之后,我发现问题可以通过将lambda声明为auto而不是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;
}

如果我可以将其声明为函数,那将会很棒 将此lambda表达式传递给其他类。

当func声明为Function时,我所遇到的错误是:

  

编程接收信号SIGSEGV,分段故障。   0x0000000000401896在std :: vector&gt; :: size(this = 0x0)/usr/include/c++/5/bits/stl_vector.h:655 655 {return size_type(this-&gt; _M_impl._M_finish - this-&gt; _M_impl._M_start);   }
  (gdb)回溯
  #d 0x0000000000401896在std :: vector&gt; :: size(this = 0x0)/usr/include/c++/5/bits/stl_vector.h:655
  std :: vector&gt; :: vector中的#1 0x00000000004015aa(这= 0x7fffffffdc50,__ x =)       在/usr/include/c++/5/bits/stl_vector.h:320
  main()中的#2 0x0000000000400d12位于test.cxx:18

2 个答案:

答案 0 :(得分:6)

(Vec) -> const Vec&相当于一个看起来像(const Vec&) -> Vec的lambda。您传递了std::function

由于调用序列包含有效转换,

std::function接受它(您可以将值传递给期望const引用的函数)。

分段错误最有可能是你的lambda(临时)的返回值固有的未定义行为被绑定到operator() std::function中的const引用;该引用正在Record之外返回,这会立即使其成为悬空参考。

答案 1 :(得分: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.
}

这编译,但是g ++警告the_function返回对临时的引用,这正是std::function所发生的事情(但没有提到编译器的提示)。

(我确信允许在std::function中转换返回值是一个错误。如果你使用的是函数指针,你就不会侥幸逃脱它,并且假设是C ++要比更安全安全,而不是更少。)