使用带有编译器优化的 std::function 类成员时出现 Segfault
Segfault when using std::function class member with compiler optimizations
我有一个非常简单的代码示例,当使用 gcc 8.2.0 下的-O2
进行优化时崩溃
#include <vector>
#include <functional>
#include <iostream>
template<typename T, typename Container>
class Lambda_Expression
{
using Lambda = std::function<T()>;
const Lambda & _lambda;
public:
Lambda_Expression(const Lambda & l) : _lambda(l) {}
T operator[](const std::size_t i)
{
std::cerr << "inside expression [] " << i << std::endl;
return _lambda();
}
};
auto lambda = []() -> double
{
return 1.0;
};
int main()
{
int N = 10;
std::vector<double> res(N, 0.0);
double x = lambda();
std::cerr << "before for loop " << x << std::endl;
auto test_expression = Lambda_Expression<double, std::vector<double>>(lambda);
for( int idx=0; idx<N; ++idx )
{
std::cerr << "loop " << idx << std::endl;
double x = test_expression[idx];
}
}
也使用-std=c++17
,以防万一。
我得到
before for loop 1
loop 0
inside expression [] 0
[1] 5288 segmentation fault ./bench_lambdas
而我希望循环运行 10 次迭代。优化级别小于 2 时不会出现此段错误。
上面的例子对我来说似乎是相当无害的代码,据我所知,2 级优化不应该破坏正确的代码。
问题:我的示例中是否存在未定义的行为或不正确的代码,或者可能是什么问题?
据我所知,这是未定义的行为。
问题是您的类注册了引用
// ..........V reference !!!
const Lambda & _lambda;
构造函数的参数
Lambda_Expression(const Lambda & l) : _lambda(l) {}
这是一个std::function
using Lambda = std::function<T()>;
但是当你用lambda调用构造函数时(如main()
auto test_expression = Lambda_Expression<double, std::vector<double>>(lambda);
您_lambda
保存对临时对象的引用lambda
因为它不是std::function
因此创建了一个临时对象,类型为std::function<double()>
,使用lambda
初始化。
所以问题来了:在构造结束时,对临时对象的引用变成了一个悬而未决的引用test_expression
所以,当你调用test_expression[idx]
时,你使用_lambda
指向(可能)垃圾。
我建议避免此类问题,避免引用部分(使_lambda
成为类型std::function
的常规成员
const Lambda _lambda; // <-- no more reference
所以你复制临时对象)
但是如果你真的想要_lambda
是对std::function
的引用,你应该写一些东西,
std::function<double()> f{lambda};
auto test_expression = Lambda_Expression<double, std::vector<double>>{f};
这样,构造函数接收到一个std::function
对象(f
)的引用,该对象在他的调用中幸存下来。
相关文章:
- 可变参数模板参数扩展 类型为 std::function 的类成员
- 是否允许类类型的 std::function 成员变量(不完整类型)?
- 将另一个类的成员函数传递到 std::function 参数中
- 如何从类成员函数返回指针,例如 size_t * class :: function(); 并使用类析构函数 ~size
- 如何将类成员函数与param绑定为boost::function的右值
- 如何返回用参数包定义的成员函数的std::function对象
- std::function是如何使指向成员函数的指针工作的
- 使用互斥锁和条件变量作为成员时如何修复"use of deleted function"?
- 使用 std::function 作为成员函数,它捕获"this",并在析构函数之后从复制的 lam
- 使用 std::function 作为具有任意数量参数的数据成员
- 将成员函数作为参数传递给其他成员函数 (C++ 11 <function>)
- std::function 可以是类数据成员吗?
- 创建具有不同成员的'Call Function'表
- 为什么我的某些数据成员"expression must be an lvalue or a function designator"收到此错误?
- 使用带有编译器优化的 std::function 类成员时出现 Segfault
- 将指向成员函数的指针转换为 std::function
- 如何使用 boost::bind 将静态成员函数绑定到 boost::function
- 将shared_ptr传递给std::function(成员函数)
- 虚重载vs ' std::function '成员
- 带有Rcpp::Function成员的c++类