4 ms·
Coming from C++ VLA are one of things that I really wish I had access too. The number of times I've seen stuff created on the heap just to toss at the end of th
by vvanders 10y ago
Coming from C++ VLA are one of things that I really wish I had access too. The number of times I've seen stuff created on the heap just to toss at the end of the block in production code always made me cringe.
Agreed that they're a very sharp tool and need to be used with care.
- cperciva 10y agoIf you want to allocate from the stack, you can usually use alloca.
- sigjuice 10y agoAnd nothing bad will happen if you alloca too much?
- cperciva 10y agoExactly the same bad things will happen as if you declare a variable-length array.
- wahern 10y agoMemory from alloca has function lifetime, while VLAs and compound literals have block scope. In a loop alloca could easily blow your stack even if you limit each allocation to something small. This is a serious pitfall, especially when using alloca with macros. The reverse is true for VLAs and compound literals in macros that return a pointer--the caller might not know that the lifetime is block-scoped and not function-scoped. Also, alloca and VLAs aren't necessarily implemented the same way. When instantiating a VLA a compiler might extend and test the stack pointer in page-sized increments so an allocation doesn't extend past the guard page without triggering a segfault. An alloca implementation might not.
- pavlov 10y agoThere's always alloca() when you want to get that small VLA-style buffer on the stack rather than heap... It's not POSIX, but ubiquitous on desktop Unixes at least.
- sigjuice 10y agoVLAs are actually not so nice. There is no sane way to handle failures if you make one too big.
- slrz 10y agoThen don't make it too big and fall back to malloc(3) above a certain threshold?
- sigjuice 10y agoDo you mind spelling out the few lines of code needed to do this?
- slrz 10y agoSomething like the following: void* pedanticmemmove(void *dst, const void *src, size_t n) { char buf[n > THRESHOLD ? 1 : n]; char *p = n > THRESHOLD ? xmalloc(n) : buf; memcpy(p, src, n); memcpy(dst, p, n); if (n > THRESHOLD) free(p); return dst; } But yeah, the alloca(3) variant is a bit nicer to look at and probably results in exactly the same code (but is non-standard, of course).
- kazinator 10y agoThe code to do what you describe is going to be nicer with alloca, because of the similarity between alloca and malloc. type *ptr = (nelem > THRESH) ? malloc(nelem * sizeof *ptr) : alloca(nelem * sizeof *ptr); /*...*/ if (nelem > THRESH) free(ptr);
- kllrnohj 10y agoC++ has way way better ways to handle this. What you do instead is a std::vector with an allocator that has a fixed-size chunk of memory to cover your common, small case and falls back to malloc if the size becomes too large to fit into the internal allocation. Then your VLA is stack allocated when small and heap allocated when large and works everywhere, even as a return value or other cases where alloca would fail. Example: https://howardhinnant.github.io/stack_alloc.html https://howardhinnant.github.io/stack_alloc.html
- vvanders 10y agoYeah, that's a much nicer solution. In the cases where it mattered we just built a standard block/arena allocator but that's a bit more work which means it was rarely used.
- deleted 10y ago[deleted]
- kazinator 10y agoThere is no reason why C99 VLA's cannot be implemented in a way which does the same thing: small enough VLA's go on the stack, and bigger ones on the heap. An unwinding mechanism in the back end can be used to do the scoped clean up. (Well, there is a possible reason: lack of integration between longjmp and unwinding cleanup mechanisms. I'm not 100% certain here, but I think VLA's are supposed to be cleaned up when abandoned by longjmp. Mind you, longjmp will also outsmart your std::vector.)
- klodolph 10y agoVLAs in C99 may be nicer syntactically than doing something similar in C++, but there are much better examples of how to do multidimensional arrays correctly. For example, how they work in Fortran is better.