35

I've been trying to figure out when things get allocated on stack and I can't figure out how would you make array (or rather values in it) get allocated on stack;

in this example:

public void foo()
{
    int bar[] = new int [10];
}

10 int structs would be allocated on the the heap, only pointer to them would be on stack, correct?

How would one make fixed size array to go on stack? What if I'm using stucts I defined?

What if I want array size passed as parameter to function?

As far as I understand there should be no problem to get array of arbitrary size on stack when function is called, if size is known when function is called.

Should I even be bothered by this? As far as I understand getting this fixed size array on stack would improve performance, because no heap allocation is done.

trincot
  • 317,000
  • 35
  • 244
  • 286
morowinder
  • 483
  • 1
  • 4
  • 6
  • 4
    `Should I be bothered by this?` probably not. It sounds like you're prematurely optimizing and thinking at too low of a level. – mason Aug 28 '15 at 15:04
  • `stackalloc` can be used for forcing a stack allocation of a certain number of bytes. It has its uses but you should be very sure you need it - most programs (especially line-of-business applications) don't need it. – xxbbcc Aug 28 '15 at 15:09
  • Stack allocated arrays were responsible for a very large proportion of all malware attacks. – Hans Passant Aug 28 '15 at 15:13

2 Answers2

34

10 int structs would be allocated on the the heap, only pointer to them would be on stack, correct?

Yes, correct.

How would one make fixed size array to go on stack? What if I'm using stucts I defined?

The stackalloc keyword serves this purpose. However, this works in unsafe context only, which is a rather unnecessarily limiting factor in most scenarios, not worth the performance tradeoff.

Example:

public void unsafe foo()
{
    int* bar = stackalloc int [10];
}

You will have to use pointer arithmetic to access members of the array.

What if I want array size passed as parameter to function? As far as I understand there should be no problem to get array of arbitrary size on stack when function is called, if size is known when function is called.

Works as expected:

public void unsafe foo(int length)
{
    int* bar = stackalloc int [length];
}

Should I even be bothered by this? As far as I understand getting this fixed size array on stack would improve performance, because no heap allocation is done.

No, in general not. Unless you deal with some very specific performance-critical scenarios, like heavy math computations, encryption, compression etc., it brings no real benefit.

Also, see this question for performance-related discussion.

Community
  • 1
  • 1
Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
  • 1
    Thanks, I love how people give really thorough explanations to somewhat trivial questions on stack overflow. – morowinder Aug 28 '15 at 15:51
  • In addition to `stackalloc` you can also allocate fixed size buffers on the stack. As an example: `unsafe struct foo { public fixed int bar[10]; }` – Gladclef May 16 '18 at 15:22
  • 14
    The addition of the `Span` type means that unsafe pointers are no longer a requirement. `public void foo() { Span bar = stackalloc int [10]; }` – EddPorter Feb 17 '20 at 14:34
  • How come it is even possible to allocate an array on the stack when the size is not known at compile time? – Algo Sep 17 '20 at 23:40
  • 3
    @algo: This is a question-and-answer site; that sounds like a candidate for a question. However before you post a question I would give it some thought first. The allocation, by definition, is not made until the program runs. Why should the fact that the *compiler* lacks certain knowledge be relevant to the runtime's behaviour? Clarify your question before you ask it. – Eric Lippert Jun 14 '21 at 20:48
7

It was mentioned in comments, but no one bother to update any answers, so I'm posting one. C# now has a special struct type that works well for this purpose:

public void foo()
{
    Span<int> bar = stackalloc int [10];
}

Taken from the docs:

Span is a ref struct that is allocated on the stack rather than on the managed heap. Ref struct types have a number of restrictions to ensure that they cannot be promoted to the managed heap, including that they can't be boxed, they can't be assigned to variables of type Object, dynamic or to any interface type, they can't be fields in a reference type, and they can't be used across await and yield boundaries. In addition, calls to two methods, Equals(Object) and GetHashCode, throw a NotSupportedException.

Span<T> Struct

James Wilkins
  • 6,836
  • 3
  • 48
  • 73