6

Here is the code:

#include <vector>
#include <functional>

class TestClass {
public:
    const std::vector<int> &getStuff() const {
        return callback();
    }

protected:
    std::function<const std::vector<int> &()> callback = []() {
        static const std::vector<int> dummy;
        return dummy;
    };
};

int main()
{
  TestClass test;

  const auto& vec = test.getStuff();
  vec.size();  // segfault

  return 0;
}

I don't understand why it should behave like this. I suspect some "known" rule about lambdas or std::functions but I cannot seem to find the right keywords for this problem so here I am.

Tested on GCC 11 and Clang 14 Ubuntu.

0

1 Answer 1

5

With this lambda:

[]() {
        static const std::vector<int> dummy;
        return dummy;
    };

The compiler infers that the return value is std::vector<int> by value (and not a reference to std::vector<int>).

Then when it is converted to a std::function<const std::vector<int> &()> the std::function will return a reference to the temporary copy returned from the lambda.

This reference is dangling and hence your SEGFAULT.

In order to fix it, you can specify the return type for the lambda explicitly:

//---vvvvvvvvvvvvvvvvvvvvvvvvvv--
[]() -> const std::vector<int>& {
        static const std::vector<int> dummy;
        return dummy;
    };

Live demo 1

As @Evg commented below, you can also use auto & to achieve the same result (the compiler will deduce the proper type and use a referece due to the &):

[]() -> auto & {
       // ...
    }

Live demo 2

5
  • 2
    6 hours jesus...not really used to explicitly declare the return types, but this is pretty eye opening tbh. I'll need to revise my old code to see how many things are doing useless copies :D
    – ligazetom
    Commented Jun 20 at 12:48
  • 2
    @ligazetom C++ is known for having many rough edges ;-)
    – wohlstad
    Commented Jun 20 at 12:51
  • 1
    I've been around C++ for +- 10 years and now I feel like that jump on rake meme. Well, see you in another 10.
    – ligazetom
    Commented Jun 20 at 12:55
  • -> auto& should also work.
    – Evg
    Commented Jun 20 at 14:01
  • @Evg - good point - added a note.
    – wohlstad
    Commented Jun 20 at 14:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.