This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Increase size of std::function small object buffer
- From: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- To: Felix Winterhalter <felix at audiofair dot de>
- Cc: "libstdc++" <libstdc++ at gcc dot gnu dot org>
- Date: Sat, 30 Jul 2016 22:07:26 +0100
- Subject: Re: Increase size of std::function small object buffer
- Authentication-results: sourceware.org; auth=none
- References: <91cb14bf-1d7a-aefd-e6bc-e49a2275ddb8@audiofair.de>
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