0

Below is a minimal code to reproduce the problem:

std::vector<std::function<bool()>> injections;
struct Obj {
    void load() {
        injections.push_back([&] {
            std::cout << ++counter << std::endl;
            injections.push_back([&] {
                std::cout << ++counter << std::endl;
                return true;
            });
            // std::cout << ++counter << std::endl;
            return true;
        });
    }
    int counter = 0;
};
int main() {
    Obj obj;
    obj.load();
    while(true)
        for(auto i = 0; i < injections.size(); i++) {
            auto pop = injections[i]();
            if(pop)
                injections.erase(injections.begin() + i--);
        }
}

Running exactly this way everything works right, but uncommenting the commented line, it crashes. The problem is that after pushing the second lambda, this points to some garbage, and the ++counter throws. I expect the first lambda to capture by reference the members, which are not gonna go out of scope after ending load(), which is what exactly happens. For the second lambda I expect to capture by reference the references, making counter available, which is again what happens using the bad line commented. It looks like the construction of the lambda invalidates everything after it. What's the reason for this and some solutions?

uIM7AI9S
  • 353
  • 4
  • 13

1 Answers1

2

When you insert something in injections, previous std::function<bool()> might be moved (and destructed).

So code after injections.push_back should no longer use captures/members.

It is mainly equivalent to usage of delete this; in a method.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • thx. I added `injections.reserve(2);` and now the code works. Though can u explain me this behavior in more detail? I don't understand why it could not use captures anymore. Is it because when it is reconstructed on moving, there's nothing to specify again the captures? Also, if using `push_back` destroys the current lambda, how can it continue execution? – uIM7AI9S Mar 12 '20 at 15:05