C++ Logo

std-proposals

Advanced search

Re: [std-proposals] C++ never had a compiler without a stack

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Wed, 16 Aug 2023 14:10:55 +0200
śr., 16 sie 2023 o 13:42 David Brown via Std-Proposals
<std-proposals_at_[hidden]> napisał(a):
>
> On 15/08/2023 19:25, Alejandro Colomar via Std-Proposals wrote:
> > Hi Andrey,
> >
> > On 2023-08-15 18:41, Andrey Semashev via Std-Proposals wrote:
> >> On 8/14/23 17:31, Alejandro Colomar via Std-Proposals wrote:
> >>> Hello Frederick,
> >>>
> >>> On 2023-08-14 13:44, Frederick Virchanza Gotham via Std-Proposals wrote:
> >>>>
> >>>> And also how about we standardise the function "alloca" which allows
> >>>> us to allocate bytes on the stack? For those not familiar with
> >>>> 'alloca', here's the Linux manual entry:
> >>>>
> >>>> https://man7.org/linux/man-pages/man3/alloca.3.html
> >>>>
> >>>> And here's a quick excerpt from that manual page
> >>>>
> >>>> The alloca() function allocates size bytes of space in the stack
> >>>> frame of the caller. This temporary space is automatically freed
> >>>> when the function that called alloca() returns to its caller.
> >>>> Because it allocates from the stack, it's faster than malloc
> >>>> and free. In certain cases, it can also simplify memory
> >>>> deallocation in applications that use longjmp or siglongjmp.
> >>>
> >>> Now that C has VLAs, alloca(3) is being removed from many projects.
> >>> In most cases, there's no guarantee that the size will fit in the
> >>> stack, and so one should use malloc(3). In the few cases where the
> >>> size is known to be small, VLAs are preferable. In fact, this is
> >>> exactly what glibc is doing at the moment: replace all calls to
> >>> alloca(3) by either malloc(3) or VLAs.
> >>
> >> I think the general direction is exactly the opposite - to get rid of
> >> VLAs wherever possible. They are also not supported in C++.
> >
> > Hmm, I've revisited the thread I was remembering[1], and yeah, they're
> > replacing alloca(3) by a fixed-size array. I was remembering wrong.
> >
> > Yeah, fixed-size arrays or malloc(3) should be preferable to alloca(3).
> >
>
> Why do you say that?
>
> Fixed-size arrays are great when you know a fixed size. But if you only
> know an upper bound, then you might be wasting significant stack space -
> and that translates to wasted cache, and slower results. This must be
> balanced against any extra code generated to handle a VLA or alloca().
>
> So if the upper bound is known to be small, go for a fixed-size array.
> And if the size is fixed (and small enough), then a fixed size array is
> definitely better than other options - but in C, remember that some
> things that would be fixed size arrays in C++ are technically VLAs in C.
> (Such VLAs with compile-time known size are as efficient as true
> fixed-size arrays.)

In C++ there is another solution that is something between static array and
VLA:

```
template<typename T, typename F>
void TempArray(int size, F func)
{
     if (size < 10)
     {
         T t[10];
         func(std::span{ t, t + size});
     }
     else if (size < 100)
     {
         T t[100];
         func(std::span{ t, t + size});
     }
     else if (size < 1000)
     {
         T t[1000];
         func(std::span{ t, t + size});
     }
     else if (size < 10000) // steps could be linear too, or specific
to fit typical usage
     {
         T t[10000];
         func(std::span{ t, t + size});
     }
     else
     {
         auto t = new [size](); //fallback to avoid exploding stack too much
         func(std::span{ t, t + size});
         delete t;
     }
}

int size;
int main()
{
    TempArray<std::string>(
        size,
        [&](auto s)
        {
            //...
        }
    );
}
```

If you really want it could even change to work with async code by
delegating to diffrent corutine, each one with fixed size.

>
> Fixed-size arrays are also easier to handle for statically generated
> stack usage analysis. Static fixed-size arrays are even easier, but if
> memory is tight (such as on small embedded systems), the inability to
> reuse the memory can be an issue.
>
> malloc() is fine for big allocations, or when you need the allocation to
> survive beyond the current scope, but it is /massively/ less efficient
> for a simple small local allocation.
>
>
> Some people argue that alloca() and VLAs are unsafe because there is no
> way to get run-time feedback if the sizes are too big and you overflow
> the stack - it's straight to UB. But they forget that bad choices of
> size for malloc() are equally bad - long before your malloc request is
> big enough to be refused, it can be big enough to push your whole system
> into slow swap space, or the joys of over-allocation of memory. So any
> code using dynamic memory allocation should ensure the size is safe
> before allocating - whether it be malloc(), alloca() or VLA's.
>
>
> What is preferable, is knowing the options, knowing their advantages and
> disadvantages, and choosing a solution that is safe, reliable,
> maintainable and efficient (and supported by the language you want to
> use). There is no universal correct answer.
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2023-08-16 12:11:08