Hacker News new | past | comments | ask | show | jobs | submit login

Remove VLAs from the language. They were a mistake.



They were made optional in C11. Compilers for DSPs or whatever where VLAs aren't practical don't have to implement them.

Just because an _optional_ feature is impractical on a few niche architectures doesn't mean it's a mistake.


> because an _optional_ feature is impractical on a few niche architectures

That isn't why it's a mistake. Arrays and the stack don't mesh well together, especially arrays that aren't bounded by anything other than the width of the integral type used for the VLA length.


Yes, but that could have been addressed by making them optional for freestanding implementations but mandatory for hosted implementations.

Are there any hosted systems (systems that can support the standard library) on which VLAs are difficult to implement?


Not as far as I'm aware. POWER, x86(_64), even Itanium all just bump a stack pointer[1]. SPARC has a funky stack, but I don't know enough about it to say how hard VLAs would be. (It's a darn cool architecture though. I wish acquiring a modern SPARC processor wasn't ridiculously expensive.)

The thing that makes VLAs hard to implement is that on some embedded and special purpose processors the stack is actually a physical, fixed-size location on the chip. I recall, but can't seem to find, some architecture that didn't use an explicit stack pointer.

1. Itanium has 2, but for purposes of VLAs it may as well have a conventional stack.


VLAs provide a very useful way to avoid making temporary allocations using malloc()/free(), allowing (generally) better speed & avoiding leaks.

Why do you believe they are a mistake?


Because malloc() can signal failure to allocate by returning a null pointer.

VLAs make it impossible to handle a failure to allocate: there is no interface to indicate what the program should do when it happens. You can only follow the declaration of a VLA with code that assumes that the allocation succeeded.


Exactly the same thing applies to fixed-size arrays. If you define a local array of N elements, there's no defined way to signal an allocation failure whether N is a compile-time constant or not.


Expanding on the above, if you create a VLA with an unchecked size derived from user input, you've got problems. If the user provides a size bigger than you can allocate, your program could crash if you're lucky. (If you're not lucky, it might appear to work but behave unpredictably.)

On the other hand, if you're currently allocating a fixed-size array that's big enough to hold, say, 1024 elements (of which you're only going to use some initial subset), then replacing it with a VLA that's the exact size you need (<= 1024) will be an improvement.

malloc() is supposed to safely tell you whether an allocation succeeded or failed, but in practice it doesn't do so reliably. On Linux, by default, it can allocate a huge chunk of address space, and then fail (with no way to handle the failure) when you try to access it. When that happens, it can invoke the "OOM killer", which can kill other processes.


But you can say the same about function calls: it may trigger stack overflow, but there's no interface to tell what to do in that case.


This is why I avoid allocating large VLAs, and using them in deep call stacks in general. There's a diminishing return for allocating on the stack beyond a certain point anyway (roughly around a page).

Having a mechanism to abstract this might be nice, but these are things people should hopefully be aware of before using VLAs. std::dynarray has been a bit polarizing though.


But malloc() doesn't always signal failure with a null in many modern systems. It will happily return you a region of unpopulated virtual address and then SIGSEGV you when you try to use it. (With overcommit).

I think we can leave VLAs in the "trust the programmer" category. Very handy with bounded sizes; it keeps you from wasting all those warm cache lines.


The OS is working around sloppy programs by allowing overcommit which is in itself sloppy (imo), if you can't trust the kernel itself the language can't really save you.


It turns out that ARMCC generates a call to malloc when you use a VLA. Was a bit of a suprrise when I used one in an ISR explicitly to AVOID malloc.

Apparently the lack of a frame pointer on ARM means that tracking dynamically sized stack frames is a problem.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: