The C compilers supplied by microcontroller vendors in particular are often, to put it charitably, not great at conforming with the latest standards.
The C compilers supplied by microcontroller vendors in particular are often, to put it charitably, not great at conforming with the latest standards.
EDIT: Fact checking myself, I found [1], so apparently they've decided to start adding C11 and C17. C99 support isn't entirely clear, though.
[1] https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-...
A parallel can be drawn to `export template` in C++98, which is a feature that was only ever implemented by a single compiler (whose engineers, when asked for recommendations to others attempting to implement, offered "don't"). As a result, it was dropped from later versions of the standard, and so almost every compiler doesn't actually support C++98 100%, but no one cares because the things that it doesn't implement doesn't matter. VLAs aren't quite as universally maligned as `export template`, but given that it's dropped to optional in later versions, it's not totally unreasonable to claim implementation of all of C99 that matters while not supporting VLAs.
Answering my own question: by doing a binary search on the online GCC documentation, I discovered that it's not documented up to 4.2.4. The next version up for which online documentation is hosted is 4.3.6, and that has -Wvla.
Naturally removing them from ISO C was the saner option.
VLA's crept in to the kernel, which is what this thread is about.
With -Wvla, you can learn about where all the VLA's are being declared in the code base.
Also, don't forget that VLA's are a GCC extension which existed before C99. They are available in the -stdc=gnu89 mode, and -ansi (without -pedantic).
They are available in -ansi mode (diagnosed if you use -pedantic).
They were not "removed" from ISO C; they are optional. If you implement VLA's, there is an ISO-C-conforming way to do that.
$ cat vla.c
int fun(int x, int a[x]) { return 0; }
int main(void) { return 0; }
$ gcc -ansi vla.c
$ gcc -std=gnu89 vla.c
$ gcc -ansi -pedantic vla.c
vla.c:1:1: warning: ISO C90 forbids variable length array ‘a’ [-Wvla]
int fun(int x, int a[x]) { return 0; }
^~~
$ gcc -std=gnu89 -pedantic vla.c
vla.c:1:1: warning: ISO C90 forbids variable length array ‘a’ [-Wvla]
int fun(int x, int a[x]) { return 0; }
^~~
This warning is now linked to [-Wvla] rather than just [-pedantic], so you can have -pedantic on, yet allow VLA's without a diagnostic. $ gcc -std=gnu89 -pedantic -Wno-vla vla.c
$ gcc -ansi -pedantic -Wno-vla vla.c
Likewise you need -Wvla to police your code against VLA's creeping in, even if you're compiling in -ansi/-std=c90 mode. Traditionally, -pedantic will do it, but it's too strong; it rejects other things you might want. For instance, in the gnu89 dialect, you can initialize local structs and arrays with non-load-time computable expressions, which is complained about with -pedantic.Dynamic allocation from the stack is something that is quite essential in some situations, and a more efficient approach compared to other alternatives in some other situations.
alloca never goes away, and VLA's are better than alloca in many ways.
You can discuss your point of view with the folks that cleaned the kernel.
https://lore.kernel.org/all/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK...
Notice that they are fully aware of that warning.
I don't know what point of view you're talking about; what the are discussing in the mailing list are silly uses of VLA that can be replaced by small arrays of fixed length sized to the worst case. These perform better, too.
This is not always practical in every situation.
C itself dynamically allocates from the stack. When a function is called, the increment in stack usage depends on which function. (If recursion is going on, it may not be easy to know the worst-case stack size, even if every function has a static frame size.)
Anyway, similarly, suppose we have used C to write a virtual machine. Suppose the virtual machine allocates function locals and temporaries on the native stack. When a VM function call is processed, the VM (a C program) has to allocate a frame for that. a VLA or alloca can provide that easily, with minimal waste.
> Anyway, some of these are definitely easy to just fix, and using VLA's is actively bad not just for security worries, but simply because VLA's are a really horribly bad idea in general in the kernel.
Code running in the kernel has a limited stack space. I think it's tiny, something like just a few pages.
Interrupts (which can nest) run in that stack space, not just the mainline code in syscall context. I think that might have changed though (there are interrupt specific stacks), which might also depend on the specific arch port of Linux. Still, those stacks are small and all the caveats apply to interrupt context. Don't be searching a linked list with linear recursion or using crazy VLA's.
If I had to put virtual machine execution into the kernel, though, I would definitely use VLA's or alloca to get the space required for each function to be as tight as possible to its actual requirements, the same way that the C compiler emits code for each function to allocate its frame size to exactly the needed size. Right tool for the right job.