tags:

views:

1414

answers:

5

I am wondering why, when in C#, if a use the set accessor to change a static class member, I get a Stack Overflow error.

I am not disputing this as a bug, I just want to know what exactly is going on in the internals of the machine.

EDIT :The question was a little unclear, sorry about that.

+44  A: 

You shouldn't; I expect you have something like:

private static int foo;
public static int Foo {
    get {return foo;}
    set {Foo = value;} // spot the typo!!! (should be foo)
}

Essentially, the set is:

static void set_Foo(int value) {
    set_Foo(value);
}

so this is recursive, and will eventually consume up the stack (assuming no optimisations, etc).

It is impossible to diagnose more without a code sample.

Marc Gravell
+1 stack overflows are usually recursion issues
Jeffrey Cameron
Not that I've ever done anything like this . . . *cough*
Jim Mischel
Could be that the static is set as the result of an event handler, and the event handler is set by setting the property (and more convoluted examples) Really need to see the code or the call stack to identify the issue
Rowland Shaw
@Rowland - maybe, but static events are usually a bad idea anyway, since if you forget to unsubscribe your object can't be collected. Ever.
Marc Gravell
Variation on the same theme is possible if you override an inherited property and forget the "base." prefix when setting.
Benjol
Hey you know what if c# had tail call optimisations then this would not even result in a stack overflow. Mind you, it would then be an infinite loop so probably not a huge improvement
1800 INFORMATION
@1800 - actually, the JIT *does* have tail-call recursion. It is implemented differently between x86 and x64, and I'm hoping there will be improvements in 4.x/5.x - but it is there. It just isn't used much.
Marc Gravell
I know that it exists in the JITter and that F# uses it, but I was under the impression that C# did not (yet, anyway).
Craig Stuntz
I agree... when it *is* used currently, it is (AFAIK) the JIT, not the language compiler, pulling the strings.
Marc Gravell
Actually the JIT tries to honour the `tail.` IL instruction prefix, if you emit it. It's only that the C# compiler doesn't, so everything is left to the JIT's discretion. F# does emit `tail.`.
Anton Tykhyy
+5  A: 

Look at your call stack in the debugger (you do stop when exceptions are thrown, right?) This should give you a strong indication of what's going on.

Rowland Shaw
Thanks for the anonymous downvote. A rationale would be useful so that others can benefit as to why this doesn't answer the question?
Rowland Shaw
Don't worry about it--a single downvote isn't that painful to your rep.
Mufasa
I don't, but it does detract from the common knowledge -- if I'm talking rubbish, it's worth explaining how I'm talking rubbish
Rowland Shaw
A: 

You want to know what's going on in the internals to cause the stack overflow?

Your method calls another method that results in infinite recursion: A calls A, stack overflow. A calls B, then B calls A, stack overflow. And so on.

As Marc Gravell suggested, it's likely theres a bug in your property implementation.

Judah Himango
+6  A: 

I'm guessing you're doing something like this:

public class MyClass
{
    public int TheInt
    {
    get
    {
     return TheInt;
    }
    set
    {
     TheInt = value; // assignment = recursion!
    }
}

The problem is, in the set function for TheInt, you're assigning a value to TheInt which will result in a nested call to the set function. You get recursion, and then a stack overflow.

Teetow
So... how do you solve this?
Rosarch
+1  A: 

I think I see a different interpretation of the question. Where the question isn't why the overflow happens, but why accessors can cause overflows. In this case, the accessor is a function call just like any other, and so it does consume stack space.

If you're using public members with no accessors, MyClass.myint doesn't become a function call, and can't overflow the stack.

davenpcj