Allgaeuer
Allgaeuer

Reputation: 775

Why is it impossible to allocate an array of an arbitrary size on the stack?

Why can't I write the following?

char acBuf[nSize];

Only to prevent the stack from overgrowing? Or is there a possibility to do something similar, if I can ensure that I always take just a few hundred kilobytes?

As far as I know, the std::string uses the memory of its members to store the assigned strings, as long as they are 15 characters or less. Only if the strings are longer, it uses this memory to store the address of some heap-allocated memory, which then takes the data.

It seems like it has to be 100%ly determined, during compile-time, how the stack will be aligned during runtime. Is that true? Why is that?

Upvotes: 1

Views: 726

Answers (7)

Ronaldo Umaña
Ronaldo Umaña

Reputation: 1

Why can't I write the following? char acBuf[nSize];

You can't do that because in C++ the lenght of the array has to be known at compile time, that's because the compiler reserves the specified memory for the array and it can not be modified during runtime. it's not about prevent a stack overflow, it's about memory layout.

If you want to make a dynamic array you should use the new operator so it will be stored in heap.

char *acBuf = new char[nsize];

Upvotes: 0

Bruno Haible
Bruno Haible

Reputation: 1282

You should be happy that the C++ standard discourages a dangerous practice (variable-length arrays on the stack) and instead encourages a less dangerous practice (variable-length arrays and std::vector with heap allocation).

Variable-length arrays on the stack are more dangerous because:

  • The available stack space is typically 8 MB, much smaller than the 2 GB (or more) of available heap space.
  • When the stack space is exhausted, the program crashes with SIGSEGV, and it requires special software such as GNU libsigsegv to recover from such a situation.
  • In typical C++ programs, the programmer does not know whether the array length will definitely stay under a limit such as 4 MB.

Upvotes: 0

Jarod42
Jarod42

Reputation: 217085

One possible problem I see with VLA in C++ is the type.

What is the type of acBuf in char acBuf[nSize] or even worse in char acBuf[nSize][nSize] ?

template <typename T> void foo(const T&);

void foo(int n)
{
    char mat[n][n];

    foo(mat);
}

You cannot pass that array by reference to

template <typename T, std::size_t N>
void foo_on_array(const T (&a)[N]);

Upvotes: 0

user3322793
user3322793

Reputation: 61

My advice is to take a look at alloca.h

   void *alloca(size_t size);

The alloca() function allocates size bytes of space in the stack frame of the caller. This temporary space is automatically freed when the function that called alloca() returns to its caller.

Upvotes: 0

user1804599
user1804599

Reputation:

Unlike C, C++ doesn't support variable length arrays. If you want them, you can use non-standard extensions such as alloca or GNU extensions (supported by clang and GCC). They have their caveats, so be sure to read the manual to make sure you use them safely.

The reason the stack layout is mostly determined statically is so that the generated code has to perform fewer computations (additions, multiplications, and pointer dereferencing) to figure out where the data is on the stack. The offsets can instead be hardcoded into the generated machine code.

Upvotes: 1

Hatted Rooster
Hatted Rooster

Reputation: 36463

Why can't I write the following?

char acBuf[nSize];

Those are called Variable Length Arrays (VLA's) and aren't supported by C++. The reason being that the stack is very fast but tiny compared to the free store (the heap in your words). Which means that at any moment that you add lots of elements to a VLA your stack might just overflow and you get a vague runtime exception. This can also happen with compile-time sized stack arrays but these are way easier to catch because the behaviour of the program doesn't influence their size. Which means that x doesn't have to happen after y to create a stack overflow, it's just there right off the bat. This covers it in more detail and rage.

Containers like std::vector use the free store which is way bigger and has a way to deal with over-allocation (throws bad_alloc).

Upvotes: 1

josefx
josefx

Reputation: 15656

It has nothing to do with preventing stack overflow, you can overflow the stack just fine with char a[SOME_LARGE_CONSTANT]. In C++ the array size has to be known at compile time, this is among other things needed to compute the size of structures containing arrays.

C on the other hand had Variable Length Arrays since C99, which adds an exception and allow runtime dependant size for arrays within function scope. As to why C++ does not have this? It was never adopted by a C++ standard.

Upvotes: 1

Related Questions