2

Stackoverflow exception occurs when a method is called recursively(infinite times)(different stack frames are allocated to each recursive call,Multiple stack frames are used in this case).As we know a stack frame is allocated to each method call.can the stack be overflown with using single method (using single stack frame).

1 Answers1

4

can the stack be overflown with using single method

Sure:

static unsafe void Main()
{
    for(int i = 0; i < 50; i++)
    {
        // fails on i=18 for me
        long* ptr = stackalloc long[10 * 1024];
    }
}

A stack overflow happens when the stack is fully consumed. There are multiple ways to do that; recursion is just one of them. stackalloc creates a pointer to (or more recently: a span over) a block of memory at the current stack-frame, extending the current stack-frame; it will be conceptually reclaimed (although in reality, this just means changing a single number) when you return (or throw, etc) from the method that allocated it.


Another way would be to create an absurdly over-sized value-type:

static class P
{
    static void Main() => Foo();
    static void Foo() => Bar(default);
    static void Bar(FatStruct2097152‬ a) => Console.WriteLine(a);
}

struct FatStruct64 {
    private long a, b, c, d, e, f, g, h;
}
struct FatStruct512 {
    private FatStruct64 a, b, c, d, e, f, g, h;
}
struct FatStruct4096 {
    private FatStruct512 a, b, c, d, e, f, g, h;
}
struct FatStruct32768 {
    private FatStruct4096 a, b, c, d, e, f, g, h;
}
struct FatStruct262144 {
    private FatStruct32768 a, b, c, d, e, f, g, h;
}
struct FatStruct2097152 {
    private FatStruct262144 a, b, c, d, e, f, g, h;
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • [How to change stack size for a .NET program?](https://stackoverflow.com/questions/2556938/how-to-change-stack-size-for-a-net-program) can be used to let less dramatic (not `unsafe`) ways to achieve it fast enough too. – Alexei Levenkov Jan 10 '20 at 07:14
  • Mark - Nice! I did not remember if there is a limit on `struct` size and if there is one how far it from default stack size so though you'd need to shrink stack anyway... but too lazy to try right now :) – Alexei Levenkov Jan 10 '20 at 07:24
  • 1
    My reaction to this abomination (FatStruct, of course) is essentially [this scene from Jurassic Park](https://media.giphy.com/media/37Fsl1eFxbhtu/giphy.gif) – ProgrammingLlama Jan 10 '20 at 07:31
  • so now stack memory is the collection of stack frames memory.if a new method is called a stack frame is allocated,what is the actual meaning of this ?(is it allocating the next block to the new method call?) – Nikhil Chitneni Jan 10 '20 at 08:33
  • 1
    @NikhilChitneni stack frames aren't "allocated" as such - the stack is just a contiguous chunk of memory; there are no blocks - it is just a chunk of virtual memory; a method call simply takes the space required for the target and parameters, (some amount) of space for the book-keeping, (some amount of space) for the locals declared by the method, and then it just increments (technically, decrements - the stack grows downwards, because reasons) the pointer to the current semantic frame within that space – Marc Gravell Jan 10 '20 at 11:29
  • what is the point calling in it as a frame?we are just allocating the memory in a sequence (i mean is there no such thing as a frame for methods,even for different method calls the stack memory is allocated contigiously right?) – Nikhil Chitneni Jan 10 '20 at 11:46
  • @NikhilChitneni I don't understand the question; can you rephrase it? – Marc Gravell Jan 10 '20 at 11:59
  • how can we differentiate from 1 frame to another ? (do frames have any starting and ending points so they can be differentiated ?) – Nikhil Chitneni Jan 10 '20 at 12:03
  • @NikhilChitneni I *expect* that it uses ESP/EBP, since that is what they are designed for... https://stackoverflow.com/a/21718937/23354; the details for how call semantics are handled are complex, and frankly not very interesting to me - they're pure runtime implementation details that you shouldn't need to care about unless you're writing / maintaining the runtime or JIT itself; however, my understanding is that somewhere between EBP and ESP is the return pointer that points to the *previous* stack location. If you need to know these details in C#: you're doing something very wrong. – Marc Gravell Jan 10 '20 at 12:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205750/discussion-between-nikhil-chitneni-and-marc-gravell). – Nikhil Chitneni Jan 10 '20 at 12:41
  • if we are calling a recursive function,are the last instruction of the first call of method and the first instruction of the second call stored in a sequential way ? this is what i actually wanted to know – Nikhil Chitneni Jan 10 '20 at 13:01
  • @NikhilChitneni assuming that the JIT doesn't choose to implement it as a tail-call (overwriting the current stack-frame), then there's nothing special about recursive calls - they're just the same as any other call, one after the other. So whatever "special way" is used: it is the same "special way" as any regular call. – Marc Gravell Jan 10 '20 at 13:32