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.
-
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
setis: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.
Jeffrey Cameron : +1 stack overflows are usually recursion issuesJim Mischel : Not that I've ever done anything like this . . . *cough*Rowland Shaw : 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 issueMarc Gravell : @Rowland - maybe, but static events are usually a bad idea anyway, since if you forget to unsubscribe your object can't be collected. Ever.Benjol : Variation on the same theme is possible if you override an inherited property and forget the "base." prefix when setting.1800 INFORMATION : 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 improvementMarc Gravell : @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.Craig Stuntz : 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).Marc Gravell : I agree... when it *is* used currently, it is (AFAIK) the JIT, not the language compiler, pulling the strings.Anton Tykhyy : 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.`. -
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?Mufasa : Don't worry about it--a single downvote isn't that painful to your rep.Rowland Shaw : 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 -
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.
-
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.
Rosarch : So... how do you solve this? -
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.myintdoesn't become a function call, and can't overflow the stack.
0 comments:
Post a Comment