1

How does this example compile and run?

#include <iostream>

int main() {
    int input;
    std::cin >> input;
    int arr[input];
    return 0;
}

My understanding is that since the input's value is not known during compile time, it'd have to be a heap allocated array. Isn't the stack space for things like arrays (without allocating on the heap) allocated when the program starts?

trincot
  • 317,000
  • 35
  • 244
  • 286
Menace
  • 417
  • 3
  • 10
  • 2
    GCC allows some illegal things by default. Compile with `-std=c++XX -pedantic-errors` to get a error. – HolyBlackCat Jul 04 '21 at 09:06
  • 1
    Bear in mind this is a non-standard extension supported by gcc. Such variable-length arrays are not a feature of standard C++. In any event, most modern compilers and host systems support manual allocation of stack space using a function named `alloc()` or `_alloc()` or `alloca()` or similar that accepts a size - but, again, this is not part of standard C++. Practically, stack space available to a process is usually much less (e.g. due to smaller process quota) than the amount of space available for dynamic memory allocation (using `malloc()`, `operator new()`, etc in standard C or C++). – Peter Jul 04 '21 at 09:10
  • @Peter Does this mean that GCC essentially manually allocates the space using `alloc()/_alloc()/alloca()`? – Menace Jul 04 '21 at 11:27
  • @Lightning - Not having looked into how gcc does it, I don't know. Documentation suggests the gnu library does include functions like `alloca()` and (presumably) one implementation choice for gcc (which does support VLAs by default, even though it's non-standard in C++) is to use something like that. – Peter Jul 04 '21 at 14:23
  • The important property that makes it implementable is that the lifetimes of such variables are nested, they are deallocated in reverse order of allocation, which is precisely what a stack is good for. – Marc Glisse Jul 04 '21 at 15:08

2 Answers2

1

My understanding is that since the input's value is not known during compile time, it'd have to be a heap allocated array.

Your understanding is correct.

Isn't the stack space for things like arrays (without allocating on the heap) allocated when the program starts?

In practice, the memory for execution stack is typically allocated when the program starts. This isn't something specified by the C++ language, but is an implementation detail.

How does this example compile and run?

The program is ill-formed. Compilers aren't required to compile the program and are require to diagnose the problem (if it doesn't diagnose it, then the compiler doesn't conform to the C++ standard). A compiler may still compile the program as a language extension. How that happens isn't specified by the C++ language.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

My understanding is that since the input's value is not known during compile time, it'd have to be a heap allocated array.

While the C++ language rules do indeed say that you can’t do this, from a technical perspective about how the call stack is typically implemented this actually isn’t necessarily true. Generally, yes, objects that don’t have a size known in advance aren’t put on the stack. However, in the case of a local variable that’s an array of variable length, it’s not that hard for the compiler to put that array in stack space. For example, the C language supports this, and this older question addresses one way of implementing it. Even though C++ doesn’t allow for variable-length arrays the way C does (technically speaking what you have here isn’t legal C++ code), some compilers allow for it.

Isn't the stack space for things like arrays (without allocating on the heap) allocated when the program starts?

This usually isn’t the case. When the program starts up, it’s allocated a region of memory and told “this is where your stack should go,” but that space is typically not determined by anything about how the program is written and is usually controlled by the OS or set by the compiler. Then, whenever space on the stack is needed - say, because a function is called or because a new block scope is entered - the program takes up some space on the call stack, handing it back when the block scope exits or the function returns.

As a result, the program doesn’t need to know at the point where it starts how much space to reserve on the stack for each function. It can defer that until the actual functions are called.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065