Why no variable size array in stack?

10,888

Solution 1

Variable Length Arrays(VLA) are not allowed in C++ as per the C++ standard.
Many compilers including gcc support them as a compiler extension, but it is important to note that any code that uses such an extension is non portable.

C++ provides std::vector for implementing a similar functionality as VLA.


There was a proposal to introduce Variable Length Arrays in C++11, but eventually was dropped, because it would need large changes to the type system in C++. The benefit of being able to create small arrays on stack without wasting space or calling constructors for not used elements was considered not significant enough for large changes in C++ type system.

Solution 2

I'll try to explain this with an example:

Say you have this function:

int myFunc() {
   int n = 16;
   int arr[n];
   int k = 1;
}

When the program runs, it sets the variables in this way onto the stack:

- n @relative addr 0
- arr[16] @relative addr 4
- k @relative addr 64
TOTAL SIZE: 68 bytes

Let's say I want to resize arr to 4 elements. I'm going to do:

delete arr;
arr = new int[4];

Now: if i leave the stack this way, the stack will have holes of unused space. So the most intelligent thing to do is to move all the variables from one place to another in the stack and recompute their positions. But we are missing something: C++ does not set the positions on the fly, it is done only once, when you compile the program. Why? It is straightforward: because there is no real need of having variable size objects onto the stack, and because having them would slow down all the programs when allocating/reallocating stack space.

This is not the only problem, there is another, even bigger one: When you allocate an array, you decide how much space it will take and the compiler can warn you if you exceed the available space, instead if you let the program allocate variable size arrays on your stack, you are opening breaches in security, since you make all the programs that use this kind of method vulnerable to stack-overflows.

Solution 3

Note that the proposal was rejected and the following is no longer true. It may be revived for a future version of C++ though.

VLA as described in N3639 has been accepted in Bristol meeting and will become part of C++14, as well as a library counter-part "dynarray". So using compiler with C++14 support we can start writing something like:

void func(int n)
{
    int arr[n];
}

Or use dynarray:

#include <dynarray>

void func(int n)
{
    std::dynarray<int> arr(n);
}

Solution 4

Simple answer: because it is not defined in the C++ standard.

Not so simple answer: Because no one propsed something behaving coherently for C++ in that case. From the standards POV there is no stack, it could be implemented totally differently. C99 has VLAs, but they seem to be so complex to implement that gcc only finished the implementation in 4.6. I don't think many people will want to propose something for C++ and see compiler manufacturers struggle with it for many years.

Solution 5

Stacks are fairly small, and their sizes can vary dramatically per architecture. The problem is that it is fairly easy to 'over-allocate' and cause a seg fault or write over memory owned by somebody else. Meanwhile, solutions to the problem (e.g. vector) have existed for a long time.

FWIW, I read Stroustrup say that he didn't want them, but I don't know which interview it was in.

Share:
10,888

Related videos on Youtube

user695652
Author by

user695652

Updated on June 04, 2022

Comments

  • user695652
    user695652 almost 2 years

    I don't really understand why I can't have a variable size array on the stack, so something like

    foo(int n) {
       int a[n];
    }
    

    As I understand the stack(-segment) of part of the data-segment and thus it is not of "constant size".

    • Mark Ransom
      Mark Ransom over 12 years
      I don't think there is any technical reason, since C99 added that capability.
    • Mooing Duck
      Mooing Duck over 12 years
      @MarkRansom: Mostly, it's tricky to do, and we already have std::vector, so they didn't require compilers to do it. On the other hand, gcc and msvc can both do it anyway.
    • Thomas Matthews
      Thomas Matthews over 12 years
      Could be because historically applications had less memory dedicated to stacks. Also stacks were a fixed structure containing local variables, parameter values and return addresses. For platforms with fixed size stacks, this feature could be dangerous.
    • Mooing Duck
      Mooing Duck over 12 years
      @ThomasMatthews: That explanation doesn't hold up in any language that supports recursion.
    • Mark Ransom
      Mark Ransom over 12 years
      @ThomasMatthews, being dangerous has never stopped a feature from being added to C++. You're expected to know what you're doing.
    • Mark Ransom
      Mark Ransom over 12 years
      @MooingDuck, any compiler that supports both C++ and C99 would be expected to allow it in C++ as an extension. As for being tricky, I can imagine quite easily how it would be implemented, and I don't write compilers.
    • Mooing Duck
      Mooing Duck over 12 years
      @MarkRansom: I didn't think so either until I realized that what if you have local variables in a more inner scope than the VLA, or two VLAs? Then the offset of each variable is no longer a constant more than the frame pointer. I can see how that might lead to complexity.
  • R. Martinho Fernandes
    R. Martinho Fernandes over 12 years
    @user695652 For starters, because there are no segments in C++.
  • Mooing Duck
    Mooing Duck over 12 years
    Both GCC and MSVC implement it, but you're right that I heard complaints from both.
  • PlasmaHH
    PlasmaHH over 12 years
    @MooingDuck: gcc.gnu.org/gcc-4.4/c99status.html seems to indicate that this wasn't easy already for C99. And with stuff like dtors and exceptions and whatnot I believe it is quite hard for C++. If it would be made standard, many more would have to implement it. I don't think many people want a second export. IMHO There are many more important things to change for future, than VLAs, which are a nice feature, but not indispensible.
  • GManNickG
    GManNickG over 12 years
    I find this answer intellectually lazy. It's not like the standard simply came into existence from nothing, people worked on it. Why didn't those people follow the route of C99's VLAs?
  • GManNickG
    GManNickG over 12 years
    Right, the question is why this is so in C++. Why didn't they follow C99's idea and add them?
  • Benjamin Lindley
    Benjamin Lindley over 12 years
    I think you're on the right track here. I can't prove this, but I believe that, for various reasons, all objects in C++ need a constant size. Why though?
  • PlasmaHH
    PlasmaHH over 12 years
    @GMan: Well, following the route of C99 VLAs in C++98 seems to be not easy for the reason of 98 < 99 ;) I think for the intrested it would be intresting to read all the mailings and proposals in the C++98 standardization process; I am not sure, but I think people proposed something, as a term to search for try "dynarray". But don't take my word for it, weak memory, you know...
  • Alok Save
    Alok Save over 12 years
    @BenjaminLindley: Constant or Non Zero size? Are you confusing the two?
  • Benjamin Lindley
    Benjamin Lindley over 12 years
    @Als: Constant. One of the reasons I think this is because I have no idea what would be expected if a VLA was passed to the following function: template<int N> void foo(int (&arr)[N])
  • Alok Save
    Alok Save over 12 years
    @BenjaminLindley: Ah,okay, that would be interesting to know if We can find more context about it in the Standard then.
  • xanatos
    xanatos over 12 years
    @GMan It isn't lazyism. It's dogmatism. It's different!
  • GManNickG
    GManNickG over 12 years
    @PlasmaHH: There is an 03 standard as well as the new 11 standard, is what I meant.
  • GManNickG
    GManNickG over 12 years
    What do you mean you're going to do delete arr;? Who ever said that would be valid? arr isn't a pointer.
  • moongoal
    moongoal over 12 years
    arr is NOT a pointer, but that would be the only (currently known) way of unallocating it. It's just a theoretical way to explain how it would work.
  • GManNickG
    GManNickG over 12 years
    We're talking about C99 VLAs, they're well-defined; no hypotheticals needed. arr is automatically allocated.
  • moongoal
    moongoal over 12 years
    Absolutely not. We are talking about why those are not implemented as a standard. And C99 VLAs are not even mentioned in the question, anyway.
  • moshbear
    moshbear over 12 years
    That, and alloca can be used with placement new[]. Though it will get rather messy in the multidimensional cases.
  • M.M
    M.M about 8 years
    Note: it was later un-accepted and did not make it into C++14.
  • einpoklum
    einpoklum over 6 years
    Please delete this answer, it is (eventually) incorrect.