简体   繁体   中英

Prevent std::function in gcc from allocating memory or increase threshhold

Is there any way to prevent std::function in gcc from dynamically allocating memory for larger function objects?

I would have expected the following code to work without dynamic allocation:

#include <functional>
#include <iostream>

// replace operator new and delete to log allocations
void* operator new (std::size_t n) {
    std::cout << "Allocating " << n << " bytes" << std::endl;
    return malloc(n);
}
void operator delete(void* p) throw() {
    free(p);
}

  class TestPlate
  {
    private:
        int value;

    public:
        int getValue(){ return value; }
        void setValue(int newValue) { value = newValue; }

        int doStuff(const std::function<int()>& stuff) { return stuff(); }

  };

int main()
{
    TestPlate testor;
    testor.setValue(15);
    const std::function<int()>& func =  std::bind(&TestPlate::getValue, &testor);

    std::cout << testor.doStuff(func) << std::endl;
    testor.setValue(25);
    std::cout << testor.doStuff(func) << std::endl;
}

However it allocates 24 bytes. As far as I am able to tell this is because the pointer to method requires 16 bytes and the pointer to the class instance another 8 bytes. This seems to be either A larger than the internal memory available to the function object or B a plain bug.

I was wondering whether there are is any way to circumvent this type of behavior without changing the signature of the std::function or creating a lot of additional wrapper code.

Unfortunately GCC's function only has space for a pointer to member function stored internally, so the result of your bind expression doesn't fit.

You can use a lambda expression instead though:

std::function<int()> f = [&]{ return testor.getValue(); };

This only requires space for a closure type containing a reference to testor (which is half the size of a pointer to member, and a third of the size of the bind result), and GCC defines that closure so it can be stored in a std::function .

Looking through the exceptionally skin-crawling functional header of libstdc++ (the default C++ library of GCC), I found out that it is in fact impossible to avoid heap allocations with its present implementation. It seems to have a special manager and invoker member that's heap-allocated, and it is required for the class to work. If you really want to look at the source, here you go , but there are definitely black arts and witchcraft going on there.

There is some functionality in the header that implies passing in custom allocators are planned, but they don't seem to be implemented at this time.

In the meantime, you could try Boost.function .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM