Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When are variable-length arrays legal?

Tags:

c++

gcc

I'm not a C++ expert, but as far as I know this code should fail due to size not being constant:

#include<iostream>

using namespace std;

int main(int argc, char** argv)
{
  int size = *argv[1] - 48;
  char array [size];
  cout<<sizeof(array)<<endl;

  return 0;
}

Why does this work when I compile that with gcc (better say g++)?

./test 7
7
/test 2 
2
like image 251
naeg Avatar asked Dec 17 '22 14:12

naeg


1 Answers

To allocate memory from stack or heap for a variable, the size of the variable need to be known. C++ compilers can decide themselves how they allocate memory, but c++ has made it public how they expect c++ compilers to handle the situation, and thus c++ std requires that compiler vendors publish their memory handling. This happens via sizeof operator. This operator is calculated completely in compile-time. The compile-time restriction for the array sizes comes from this requirement.

int arr[10];
std::cout << sizeof(arr) << std::endl

since every variable and type supports sizeof, their sizes need to be calculated on compile-time in c++. Thus variable-length arrays are impossible in c++.

There is another very important restriction flowing from this requirement. In principle c++ compiler vendors could calculate maximum amount of memory required for c++ program's stack, if only there weren't one problem: for recursive functions, you cannot calculate stack size used by the program, but for everything else, the size of stack can be calculated by doing the following:

  1. use sizeof(a) for every variable in stack frame
  2. sum the sizes of the variables to get amount of memory required for that stack frame
  3. list all possible stack frames and calculate their sizes
  4. Pick the call stack that has largest size
  5. choose that size as the size of your program's stack.

Unfortunately, recursive functions break the whole scheme. And it would need global program's flow analysis to regognize which functions have possibly infinite call stacks. But the limitation for compile-time sizeof operator is important or our c++ programs would randomly run out of stack space, causing crashes and unstability. And this is unacceptable. Thus every variable and type supports compile-time sizeof operator.

VLA support requires that compilers can generate code where offsets normally generated to as constants to the resulting machine code are actually modifiable on runtime. Standard conforming c++ compilers normally do not have ability to do this. C decided to add this support and thus C compilers can do it. But in the process they needed to break the sizeof operator. No longer can the sizes be calculated on compile-time. VLA support as specified in the C standard has big problems:

  1. you cannot put VLA inside a struct or class
  2. VLA's are basically restricted to the local function scope

These problems were already solved in c++ via std::vector which do not have any of these problems.

like image 146
tp1 Avatar answered Dec 19 '22 03:12

tp1