+ 2

Why does core c++ not support VLA?

I pre-assume that VLA is not supported by core c++ but some compiler do support it... Is it correct till date ? Additionally, I noted that VLA isn't supported as it impact the performance... How does it impact is not I am able to digest..

3rd Aug 2020, 4:13 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
6 Answers
+ 2
If I had to guess, it's that without VLAs we can know the size of every function's stack frame at compile time. With VLAs we can't, which means the compiler has to do more work and it possibly rules out some compiler optimizations. Example: function foo() { int a; int b; } Here we know that `a` lives at offset 0 and `b` at (probably) offset 4 and the compiler can pretty easily turn variable names to a pointer dereference, e.g. `b` can be turned into `*(stack_ptr + 4)`. But then consider this: function foo() { int a; int b[variable]; int c; } I think here we can determine stack frame offsets only at runtime, after we resolve how large the array is. I'm sure there must be some performance penalty. As ~ swim ~ said vectors are more convenient anyway so not having VLAs isn't that bad of a tradeoff.
3rd Aug 2020, 6:28 PM
Schindlabua
Schindlabua - avatar
+ 2
Schindlabua and ~ swim ~ thanks a lot.... I got it that it's difficult to predict size at compile time by compiler and stack frame becomes difficult.... All points are valid and makes sense but still vector is allocating on heap and would not it be better to have something on stack itself ?
3rd Aug 2020, 7:59 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 2
The heap is slow, that's true. I guess we have to discriminate: - You are doing very few allocations: The heap performance hit is negligible. - Your arrays are very large: You have to allocate on the heap regardless. - You are doing a lot of small allocations: Well.. You could set a maximum array size, as is common with buffers: `char buf[256];` That maybe wastes some space but should be good for the vast majority of applications. And uh, for the rest, people have written stack allocators to allocate on the stack dynamically, so it is possible, but complicated. Above my paygrade really. If you seriously need to consider this you will probably write a better allocator altogether (game engines come to mind, they often do) You could also roll a custom stack, on the side, that holds some memory and gives it out to arrays (it's just a large array and a pointer moving around in it). The C++ designers must have concluded that the usecases don't warrant the effort. People don't seem to miss VLAs either.
3rd Aug 2020, 9:12 PM
Schindlabua
Schindlabua - avatar
+ 1
All answer about the stack allocation are simply wrong. The reason of absence of VLAs in C++ is very different. VLAs are a part of a larger family of Variably Modified types. This family of types is very special because they have *runtime* components. The code: int A[n]; Is seen by compiler as: typedef int T[n]; T A; Note that the runtime size of array is not bound to the variable `A` but to the **type** of the variable. Nothing prevents one from making new variables of this type: T B,C,D; or the pointers or arrays T *p, Z[10]; Moreover, pointers allow one to create VLAs with dynamic storage. T *p = malloc(sizeof(T)); ... free(p); What dispels a popular myth that VLAs can only be allocated on stack. Back to the question. This runtime component does not work well with type deduction which is one of the bases with C++ typing system. It would not possible to use templates, deduction and overloading. C++ typing system is static, all types must be fully defined or deduced during *compilation*. VM types are completed only during program *execution*. Additional complexity introducing VM types to already hellishly complex C++ was simply considered unjustified. Mainly because their main practical application are automatic VLAs (`int A[n];`) which have an alternative in form of `std::vector`. It a bit sad because VM types provides very elegant and efficient solutions to programs handling multidimensional arrays. In C99 one can simply write: void foo(int n, int A[n][n][n]) { for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) for (int k = 0; k < n; ++k) A[i][j][k] = i * j * k; } ... int A[5][5][5], B[10][10][10]; foo(5, A); foo(10, B); Now try to provide as efficient and elegant solution in C++.
22nd Sep 2021, 9:31 PM
Tomasz Stanislawski
Tomasz Stanislawski - avatar
0
Tomasz Stanislawski Could you elaborate on what other types fall into the variably modified family? Wouldn't the point of hiding the definition behind a typedef be so that the compiler can tag the type as "runtime-sized" which then circles back to what I said about the compiler not being able to figure out stack frame sizes? Are there any exceptions to the rule that a compiler always must know the size of any given type? That is, are there situations where the compiler *can't* figure out the size of a stack frame? Do any variably modified types exist in C++? EDIT: I guess not only stack frame sizes wouldn't be known but also the size of generics and other things so maybe that was your point.
24th Sep 2021, 9:54 AM
Schindlabua
Schindlabua - avatar
- 2
ŰłÙ„Ű§Ù…
8th Aug 2020, 11:03 AM
Amir