3

Can I delete a std::function object from within the function being called by its operator()? Like this:

#include <functional>
#include <iostream>

int main() {
    std::function<void()>* fn = nullptr;
    fn = new std::function<void()>([&fn](){
        std::cout << "In my lambda\n";
        delete fn;       // Is this undefined behaviour?
        // fn = nullptr; // This definitely *is* undefined behviour!
    });
    (*fn)(); // Call lambda
    return 0;
}

This is a very stripped down version of the true situation. The real code smart pointers rather than explicit new and delete (of course), and really the function is removing itself from an STL data structure.

I am interested in two questions:

  • Is this definitely not undefined behaviour according to the C++ standard?
  • Do implementations allow this in practice? Even if this is allowed in theory, if it's such an unusual edge case that implementations may crash in practice then I still want to avoid it!

Similar questions that have been asked before:

  • This is similar to the many questions about delete this (e.g. Is delete this allowed). This question is different though because it depends on the library part of the standard as well as the language: if std::function is allowed to access any member variables after it calls its contained function then this is undefined behaviour.
  • There are one or two questions that are more similar to this one (e.g. std::function delete-itself when during its call?) but they seem to be interested in, roughly speaking, whether it's probably going to be alright in their application rather than whether the C++ standard specifically allows it. Certainly none of the answers I've seen have mentioned the C++ standard for std::function.
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Arthur Tacca
  • 8,833
  • 2
  • 31
  • 49
  • That doesn't really make any sense to me. Why would you ever use a pointer to a `std::function`? What is the use-case? What is the *Actual* problem you want to solve using pointers to `std::function`? And no, you can't `delete fn` in the function, because the lambda is a temporary object of an unnamed class that the compiler generates, and the variable `fn` is a member of that class (implementation detail though, but basically the only sane way to implement captures), and by deleting `fn` you kind of pull your own rug out from under yourself. – Some programmer dude Jun 03 '18 at 11:47
  • 1
    @Someprogrammerdude [citation needed] – melpomene Jun 03 '18 at 11:47
  • I don't really see any difference from `delete this`. `std::function` is just another class that doesn't use any intrinsics. You could implement it yourself just as well. – Mikhail Vasilyev Jun 03 '18 at 12:18
  • 1
    @MikhailVasilyev The fact that `delete this` is allowed doesn't stop there being a problem with `std::function`, because perhaps during `operator()` it could access one of its data memebers after calling the user function (which in my case would `delete this`), which would definitely cause undefined behaviour. Unless the standard explicitly says that implementations cannot do this, then it could potentially occur. – Arthur Tacca Jun 03 '18 at 13:54
  • @Someprogrammerdude I am using a [`grpc::CompletionQueue`](https://grpc.io/grpc/cpp/classgrpc_1_1_completion_queue.html), whose API is outside of my control. When an event completes, all you get back to identify the event is a `void*`, and `std::function` has larger footprint than a regular pointer so this `void*` must be a pointer to the function, which I must allocate on the heap (potentially as part of a larger struct). The context is a larger application with more details than I can fit into a comment. – Arthur Tacca Jun 03 '18 at 13:56

0 Answers0