Increase size of std::function small object buffer
Jonathan Wakely
jwakely.gcc@gmail.com
Sat Jul 30 21:07:00 GMT 2016
On 30 July 2016 at 13:27, Felix Winterhalter <felix@audiofair.de> wrote:
> Hello all,
>
> so I've run into the following problem.
>
> I'm using gcc's libstdc++ to do embedded development. In this case its
> usually fairly important to make sure that all dynamic allocation is
> controlled or best not done at all.
>
> I've been using std::function to implement various callbacks and only
> yesterday found out by accident that it actually performs dynamic
> allocation for a case where its rather surprising: std::bind of method
> pointers with class instances.
>
> I've already started a small discussion on stack overflow:
> https://stackoverflow.com/questions/38667268/prevent-stdfunction-in-gcc-from-allocating-memory-or-increase-threshhold/38670041#38670041
>
> and in the gcc irc channel. I'm going to add my example code here as well.
>
> Essentially the gist is the following:
>
> std::function<int()> a = freeFunction; // No dynamic allocation
> std::function<int(Class*)> a = &Class::Method; // No dynamic allocation
> std::function<int()> a = std::bind(&Class::Method, &classInstance); //
> Dynamic allocation!!!
>
> The problem is that this is actually rather unexpected behavior in my
> opinion as I would assume that having a bound method pointer function is
> something you'd definitely want to support without dynamic allocation.
>
> It gets even worse when you take into account one answer on stack
> overflow which says that:
>
> std::function<int()> f = [=]{ return classInstance.Method(); };
>
> Actually does not perform dynamic allocation. I would however expect
> this to be more of a clever workaround than the way the standard would
> want you to use this since this is not an instance of very transparent code.
No, lambdas replace almost all uses of std::bind, and have several
advantages (like this one).
It's not a hack or a clever workaround, it's a better solution.
> I see a simple solution to this:
>
> Increase the internal buffer of std::function to 24 bytes from 16 bytes
> as the method pointer uses 16 bytes while the pointer to class instance
> uses another 8 bytes.
That would break the library ABI, so is not an option.
>
> On a side note:
>
> Clangs libstdc++ does not perform dynamic allocation here
>
> also
>
> Using a custom allocator is not a solution as it will not carry over to
> value copies of the std::function object (this appears to be a defect in
> the standard which they however do not acknowledge as such) see:
> https://stackoverflow.com/questions/32596021/whats-the-point-of-stdfunction-constructor-with-custom-allocator-but-no-other
> and
> https://cplusplus.github.io/LWG/lwg-closed.html#2386
GCC doesn't implement the constructors taking allocators, and I
removed allocator support from std::function in C++17:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0302r1.html
More information about the Libstdc++
mailing list