Stack overflow exception without infinite loop (as

2019-07-15 09:28发布

I have a stack overflow error, and I'm fairly sure I don't have any kind of infinite recursion (at least I've stared at the error for a few hours now and I can't imagine how its looping infinitely).

Here is the code:

    public decimal? Amount
    {
        get
        {
            if (!string.IsNullOrEmpty(_savedWork.Amount))
                return decimal.Parse(_savedWork.Amount);
            else
                return null;
        }
        set
        {
            if (value.HasValue)
            {
                _savedWork.Amount = value.Value.ToString();
                Percent = null;
            }
            else
                _savedWork.Amount = "";
            OnPropertyChanged("Amount");
        }
    }

#Note I have a string housed in a nullable decimal, that's why I'm converting it. Please don't make me go into why I'm doing this.

the line savedWork.Amount = value.Value.ToString() is where I get the error.

Basically I'm thinking that my stack is just too small (or my code is too big I suppose). I basically run this code twice, and it works when in one form, but not when I make another form and place it in there, so I think the difference between these 2 forms is tipping the stack.

Is there a way to identify what I'm doing wrong? I want to find out what part of the code is taking up a too much or is persisting too long etc.

I've done some research about how the stack/heap work and I know about PerfMon.exe, but as far as I know it only works for the heap. Is there a similar tool that I can use for the stacks my program is running?

I found this post about 2 tools called windbg and cdb but I can't find much about how to install/use them. Are these tools the right way to go?

Alternatively if there is an infinite loop or something that would be great.

Edit

here is the code requested for the Amount Property (its autogenerated by EntityFramework) as I said in the comments, the step into doesn't even reach here. I really do think my stack limit is just being reached.

  public global::System.String Amount
    {
        get
        {
            return _Amount;
        }
        set
        {
            OnAmountChanging(value);
            ReportPropertyChanging("Amount");
            _Amount = StructuralObject.SetValidValue(value, true);
            ReportPropertyChanged("Amount");
            OnAmountChanged();
        }
    }

Final Edit

Ok so Meta-Knight's answer showed me that I did indeed have an infinite loop. I had an event handler subscribed to the PropertyChanged event of the DisplayTypeOfInvestment (the class that the Amount Property belongs to). The handler looked like this:

 void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
            _typeOfInvestmentFormSavedWork.TypeOfInvestment.Clear();
            foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
            {
                _typeOfInvestmentFormSavedWork.TypeOfInvestment.Add(d.SavedWork);
            }

            OnPropertyChanged("TypeOfInvestmentFormSavedWork");

    }

The TypeOfInvestmentFormSavedWork is a completely different class that contains in it it's own version of the SavedWork class that we see that is used an the Amount property. The point of this method was to update this TypeOfInvestmentFormSavedWork property to the new value of _savedWork when the Amount property changes. For some reason this is triggering the DisplayTypeOfInvestment viewmodel's PropertyChanged. I didnt figure it out but I changed the method to look like this:

 void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Amount" || e.PropertyName == "Percent")
        {
            _savedWork.TypeOfInvestment.Clear();
            foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
            {
                _savedWork.TypeOfInvestment.Add(d.SavedWork);
            }

            OnPropertyChanged("CurrentWork");
        }
    }

The if statement stops the weird properties being changed in the DisplayInvestmentFund when the Add method is called.

I realise this answer doesnt make much sense, but for me to explain this in full detail would take a very long time. I also realise that this probably means my code is bad. I'm not sure what to do about that. Thanks for the help guys.

4条回答
何必那么认真
2楼-- · 2019-07-15 09:41

My guess is that you're assigning to Amount in one of the event handlers that OnPropertyChanged calls.

Another possibility is that you have code in the setter of SavedWork.Amount that calls YourClass.Amount again.


But why don't you just debug it? Just step through the code in the Visual Studio debugger.

The stack trace should also be useful. With endless recursion you typically get a repeating sequence of methods. If my guess is correct the repeated part will be something like:

MyClass.set_Amount
MyClass.OnPropertyChanged
OtherClass.myClass_amount_changed
查看更多
疯言疯语
3楼-- · 2019-07-15 09:43

Is the class of which Amount member of the same type as _savedWork?

Because there could be this loop:

1) You assign a value to Amount

2) Before the value is set, you assign a value to _savedWork.Amount

3) Before the value of _savedWork.Amount is set, the line is triggered again

4) Before the value of _savedWork._savedWork.Amount is set...

5) Before the value of _savedWork._savedWork._savedWork.Amount is set...

And this goes to infinity and beyond.

查看更多
别忘想泡老子
4楼-- · 2019-07-15 09:48

Is _savedWork an object of the same type as the Amount property you listed? Because that will give you a stack overflow error! In that case, you need to find a way to talk about Amount without invoking the getter and setter.

查看更多
小情绪 Triste *
5楼-- · 2019-07-15 09:51

There must be a recursive call to the Amount setter somehow. You could debug it by "stepping into" the properties instead of stepping over. If you set VS so that it doesn't step into properties, you can still put a breakpoint inside your setters to simulate a "step into". As for VS not stepping into .edmx files, as CodeInChaos mentioned, maybe the class is tagged with a DebuggerStepThrough attribute.

查看更多
登录 后发表回答