Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 773
Blackclaws Avatar asked Jul 29 '16 20:07

Blackclaws


People also ask

Does STD function allocate memory?

The reason for the dynamic memory allocation is that std::function is generic and has no idea how much data you captured, but that captured data has to exist inside of a std::function and also has to be able to be copied as a std::function is moved around or copied to other locations.

How do you allocate a block of memory in C++?

Use the malloc() function to allocate memory in designated blocks and the new function to create memory in the free store (heap). To reallocate memory, the realloc() function is used. When finished, always include a free() function in order to free up the memory. If you used new(), use delete() to free up the memory.

Why is the heap slower?

Heap memory is slightly slower to be read from and written to, because one has to use pointers to access memory on the heap. We will talk about pointers shortly. Unlike the stack, variables created on the heap are accessible by any function, anywhere in your program.


1 Answers

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.

like image 146
Jonathan Wakely Avatar answered Oct 17 '22 00:10

Jonathan Wakely