Search code examples
c++stdvectorstd-function

Self modifying vector of std::function segfault


I'm trying to define a vector of function. When the functions are called they can add or remove items from the vector.

Ultra simplified it's something like the code below.

#include <functional>
#include <vector>

int main()
{
    using F = std::function<void()>;
    std::vector<F> v;
    v.push_back([&v]{
        puts("v0");
        v.push_back([]{puts("v1");});
        v.push_back([]{puts("v2");});
        v.push_back([]{puts("v3");});
        v.push_back([]{puts("v4");});
        v.push_back([]{puts("v4");});
        v.push_back([]{puts("v5");});
        v.push_back([]{puts("v6");});
    });
    v[0]();
}

The code compiles fine, but when run it segfault when calling the V0 function.

$ v0
$ Erreur de segmentation (core dumped)

I understand the problem is related to vector reallocation (because if I add a v.reserve(10); before calling V0 it works fine), but I still don't understand what is wrong with that code and why it doesn't/shouldn't work.


Solution

  • but I still don't understand what is wrong with that code and why it doesn't/shouldn't work.

    When the vector reallocates, the objects stored inside it are destroyed after having been copied.

    So, lambda that is being executed has been destroyed, and when you attempt to access the captured reference v of the destroyed lambda, the behaviour of the program is undefined.

    If the move constructor of std::function was noexcept (and it will be in C++20), vector would move the elements instead, in which case the lambda would remain intact.