Search code examples
c#wpfxamlentity-framework-4stack-overflow

Stack overflow exception without infinite loop (as far as I can tell)


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.


Solution

  • 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.