简体   繁体   English

使用带编译器优化的std :: function类成员时的Segfault

[英]Segfault when using std::function class member with compiler optimizations

I have a quite simple code example which crashes when optimized with -O2 under gcc 8.2.0 我有一个非常简单的代码示例,当在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];
    }
}

Using also -std=c++17 , in case that makes a difference. 使用-std=c++17 ,如果-std=c++17

I get 我明白了

before for loop 1
loop 0
inside expression [] 0
[1]    5288 segmentation fault  ./bench_lambdas

whereas I would expect the loop to run for 10 iterations. 而我希望循环运行10次迭代。 This segfault does not appear with optimization level less than 2. 优化级别小于2时,此段错误不会出现。

The above example looks like fairly harmless code to me and as far as I know level 2 optimizations should not break correct code. 上面的例子看起来对我来说是相当无害的代码,据我所知,2级优化不应该破坏正确的代码。

Question: Is there undefined behaviour or incorrect code in my example or what might be the issue? 问题:我的示例中是否存在未定义的行为或错误的代码,或者可能是什么问题?

As far I know, it's undefined behaviour. 据我所知,这是未定义的行为。

The problem is that your class register the reference 问题是您的类注册了引用

// ..........V  reference !!!
const Lambda & _lambda;

of the argument of the constructor 构造函数的参数

Lambda_Expression(const Lambda & l) : _lambda(l) {}

that is a std::function 这是一个std::function

using Lambda = std::function<T()>;

But when you call the constructor with a lambda (as in main() ) 但是当你用lambda调用构造函数时(如在main()

auto test_expression = Lambda_Expression<double, std::vector<double>>(lambda);

you save in _lambda the reference to a temporary object because lambda isn't a std::function so it's created a temporary object, of type std::function<double()> , initialized with lambda . 你在_lambda保存对临时对象的引用,因为lambda不是std::function所以它创建了一个临时对象,类型为std::function<double()> ,用lambda初始化。

So the problem: the reference to the temporary object become a dangling reference at the end of the construction of test_expression so, when you call test_expression[idx] , you use _lambda that is pointing (potentially) to garbage. 所以,问题:引用了临时对象成为施工结束悬空参考test_expression所以,当你调用test_expression[idx]您使用_lambda被指向(可能)垃圾。

I suggest to avoid this sort of problems avoiding the reference part (make _lambda a regular member of type std::function 我建议避免这种避免引用部分的问题(make _lambdastd::function类型的常规成员

const Lambda _lambda;  // <-- no more reference

so you copy the temporary object) 所以你复制临时对象)

But if you really want that _lambda is a reference to a std::function , you should write something as follows 但是如果你真的想要_lambda是对std::function的引用,你应该写如下内容

std::function<double()>  f{lambda};

auto test_expression = Lambda_Expression<double, std::vector<double>>{f};

This way the constructor receive a reference to a std::function object ( f ) that survive to his call. 这样,构造函数接收对std::function对象( f )的引用,该对象在其调用后仍然存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 std线程调用模板成员函数模板类:编译错误 - std thread call template member function of template class: compiler error 在模板化成员函数的返回类型中使用 std::enable_if 时的编译器差异 - compiler differences when using std::enable_if in return type of templated member function 使用std :: vector的插入成员函数插入std :: vector时出现段错误 - Segfault on inserting into std::vector with insert member function of std::vector 在模板化类中将`std :: sort`与成员函数一起使用 - Using `std::sort` with a member function in a templated class 访问类的数组成员时出现段错误 - Segfault when accessing array member of class 尝试访问类的字符串成员时出现段错误 - segfault when trying to access a string member of a class 尝试访问库中成员的功能时出现段错误 - Segfault when trying to access function of member in a library 使用派生类中的成员初始化父类中的std :: function - Initialise std::function in parent class using member in derived class std::atomic 作为 class 成员:使用 boost/python.hpp 时使用已删除的 function 错误 - std::atomic as class member: use of deleted function error when using boost/python.hpp 使用std :: bind将类成员函数注册为函数的回调 - Registering a class member function as a callback to a function using std::bind
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM