Monday, January 12, 2009

Exceptions 101: StackOverflowException

Underwater cave exploration is notoriously dangerous. Because of this, divers who explore these caverns unravel string behind them as they swim, so they can find their way back to the surface at the end of their dive. .NET does something similar, creating a record of methods, adding and removing from this record as the application enters and exits specific methods. This trail is called the call stack, and at any given time, it shows what steps were taken that led to the current method. The difference between the diver and the application, however, is that when the diver runs out of string, he turns back and returns to the surface, but when too much stack has been laid down, the application throws a StackOverflowException.



The typical reason for a StackOverflowException is a recursive call made within the code. The following console application gives an example:


public class Program

{

    static void Main(string[] args)

    {

        RunA();

    }

 

    static void RunA()

    {

        RunB();

    }

    static void RunB()

    {

        RunA();

    }

}



Following the logic of this application, it's simple to see what happens. The main program calls a method called RunA, which in turn calls RunB, which in turn calls RunA, and so on and so forth. This loop never stops, so .NET stops it for you by throwing a StackOverflowException.

Now, here's the bad thing about a StackOverflowException, typically, in the IDE, whenever you try to view detail on a StackOverflowException, you get this really wonderful and informative line:

{Cannot evaluate expression because the current thread is in a stack overflow state.}

"Great," you say, "not only am I getting an exception, but I can't even view any information about it." Not only this, but you can't catch a StackOverflowException either. Sounds fun, huh?

There's no need to fret. In this situation, the simplest thing to do is to read the call stack from the call stack window. You can access this window by going to Debug -> Windows -> Call Stack, or by simply pressing Ctrl-Alt-C. When you view the call stack, you'll most likely notice that it's full. It probably has thousands of lines on it. The key here is to find the pattern which will most likely be there. In my small example above, the beginning of the call stack looks like this:



See the pattern? Granted, this is a very simplistic example, as there are only two methods recursively calling each other. Debugging this may take a little more effort in real life, however, and it may vary from situation to situation. I may have to ask myself why I'm calling RunB from RunA, and why I'm calling RunA from RunB. It could be that I don't really mean to call one from the other, and it could be that some condition I should have implemented to prevent one from calling the other at some point is never being evaluated in such a way as to stop the recursive calls. In any way, the key to at least finding this error is to take a look at the call stack, and read it until you start seeing it repeat itself, and somewhere in that loop, cut it off or redirect it to another method.

By the way, it's important to check your properties as well, as codependant properties can cause this very same error. Remember, property getters and setters are nothing more than prettied-up methods.

Happy debugging!

Friday, January 9, 2009

Exceptions 101: ArgumentNullException

Today's Exception is the ArgumentNullException. The Message for this exception will usually start out with "Value cannot be null", it will then be followed by the name of the parameter.


This specific exception is thrown by the .NET Framework (or by you, if you choose to) whenever a method is expecting a non-null instance of an object as a parameter, but receives a null value. This exception exists to prevent the NullReferenceException from being thrown, and to prevent other unpredictable, unstable (and otherwise nasty) actions from the methods that try to use the value, and the objects that may use them later. Imagine if you continued passing null to some obscure private method down in the depths of your application, and then suddenly received a NullReferenceException. There's a situation that may be even worse... What if your application continued running happily and never warned you that you had passed in a value that was null until 3 hours after it happens?! This is the kind of thing that can happen when ArgumentNullExceptions aren't thrown. Trust me, this exception is your friend.

So how do you debug an ArgumentNullException? Fortunately, the designers of .NET saw to it that most of the times they throw the ArgumentNullException, it's thrown from within a public method. Where it's not thrown in a public method, it's pretty close under the surface. This means, you don't usually have far to look. Typically, this information comes from a combination of the stack trace and the error message itself. Let's take a look at an example:




using System;

 

class Program

{

    static void Main(string[] args)

    {

        string value = null;

        TimeSpan timeSpan = TimeSpan.Parse(value);

        Console.WriteLine(timeSpan);

        Console.ReadLine();

    }

}




Now, in the code above, we're doing a very simple task; parsing a string to create a TimeSpan object. There's only one problem. The value we want to parse is null! Now, let's just pretend for a second that it isn't so obvious which value is null. (Pretend I got value from a database.) So, I get this string value back and I pass it into the TimeSpan.Parse static method. All the sudden I get this ArgumentNullException.

Let's take a look at the first few lines of the stack trace. To view the exception detail, click the little link on the exception window (like the one above) and a new modal window will appear with information about the exception. When you click the text area to the right of "StackTrace", you'll see a little down arrow that you click to open the exception detail. Your screen should now look like this:





Here's the first part of the stack trace:

at System.TimeSpan.StringParser.Parse(String s)
at System.TimeSpan.Parse(String s)
at Program.Main(String[] args) in ... (truncated for simplicity)


The top line of our stack trace is where this exception is getting thrown. Now let's take a look at the error message:


Value cannot be null.
Parameter name: s



So this is saying that the parameter s that was passed into the System.TimeSpan.StringParser.Parse method is null, and the method was expecting a non-null string value. Internally, StringParser.Parse calls a method that checks if s is null. If it is, then StringParser.Parse throws an ArgumentNullException. Without an actual string value, the Parse method isn't going to work properly, so it throws an exception.


Now, looking at the method that called System.TimeSpan.StringParser.Parse, we see that it only takes one parameter, of type string, called s, so we are probably safe to assume that we should check the parameter values that we pass into the method, to see if any of them are null. In this situation, we see that value is null, and we're safe to assume (in this situation) that our value property is the culprit. And indeed, if we change the string (to a string that can be parsed), then we get a proper result.

This exception should be thrown whenever you absolutely, positively, need a value to not be null, and someone's trying to get one past you. If at all possible, throw this exception in your public methods, as early as possible in the code execution.

Wednesday, January 7, 2009

Exceptions 101: ArgumentOutOfRangeException

Today's exception is the ArgumentOutOfRangeException. This exception is thrown whenever an argument passed into a method is outside of the accepted range for that value, thus, this exception should only ever be thrown in code for data types that have an actual range. For example, while Int32 has a range, Point does not have a range. However, the property X on Point does have a range, and it's range is the same as the range between Int.MinValue an Int.MaxValue. By the very definition of "Range", some data types should be simply excluded from being the root of the cause for this error.


The most common reason for an ArgumentOutOfRangeException is when your code is trying to access an element of a collection by it's numerical index in the collection, but the index passed in is lower than the index of the first item or higher than the index of the last item. For instance, let's say I have the following list of strings:

As you can see, I have six items in this list, and the indexes for them range from 0 to 5. Now, let's say I take this array and make the following code with it:

using System;

using System.Collections.Generic;

 

class Program

{

    static void Main(string[] args)

    {

        List<string> list = new List<string>() 

        { "David", "Morton", "is", "the", "coolest", "guy" };

 

        for (int i = 0; i <= list.Count; i++)

            Console.WriteLine(list[i]);

 

        Console.ReadLine();

    }

}


Now I'm going to be getting an ArgumentOutOfRangeException. The reason for this, is that I've defined my loop incorrectly. The Count property of the list is 6, because there's six items in the list, but if you look at the index values above my items, you'll see that the indexes only go up to 5. Apparently, the indexer property for List<T> is zero-based, and not one-based, which means the first item in the list actually has the index of 0, while the last item has an index of 5.

Debugging this may look a little daunting at first, mainly because my call doesn't look like an actual method call in this situation. For starters, I'm not calling any "dot" methods, such as list.Count. Instead, I'm calling what's called an indexer property, which is parameterized. This special kind of property doesn't appear to have a name in C#, and instead, takes a parameter, in square brackets, and uses that parameter to return a value. Nevertheless, don't be fooled by the brackets instead of the parenthesis. Behind the scenes, list[i] is really calling a method that is part of the property, and that i value gets used.

Back to the issue at hand... now that you know that it's the [i] that's throwing the property (if you're not sure which piece of code is throwing the error, break down your line of code and enter it into the watch window. See the article on NullReferenceException for more on how to do that), you can step through the code to evaluate the indexer value as the for loop makes it's iterations.

First, add a break point on the offending line. You can do this by clicking in the gray vertical bar just between the text editor and the edge of the window. When you do that, you'll see a red dot appear, and the entire line will be highlighted in red.

Next, run your application. The application should stop executing on the line with the break point. Now you need to open the locals window. To do this, go to the Debug window, and click "Windows" followed by "Locals", or just press Ctrl-Alt-V, followed by L.

Now, press F5. You should see the value next to i turn red and the value should change. Keep doing this until you see the exception thrown. When you see the exception thrown, you'll notice that the value of i is 6. No exception was thrown when the value was 5, so now we've found our problem. We'll just change the <= in the for statement to a <. This solves the problem.

Hopefully today you've seen how to debug yet another exception. I'll have another for you friday.

Monday, January 5, 2009

Exceptions 101: NullReferenceException

So, I've decided to start a series on exceptions. We've all seen them, and we've all had to work with them, but if you're early in your development career, you may not know exactly what each one of these means, why you're getting them, and what to do about it. So, I've decided to create a series on exceptions. Each post in the series is going to detail a specific exception, why you're getting it and how to get it to stop. Today's exception is the NullReferenceException.



The NullReferenceException is thrown whenever you're trying to use an object (either a class, or a Nullable type) that is currently set to null. It's typical message is "Object reference not set to an instance of an object". It differs from the ArgumentNullException, which I'll talk about in my next post, in that a NullReferenceException is thrown at runtime whenever the instance of the object is used, whereas the ArgumentNullException is thrown whenever a required parameter in a method is passed in as null. Think of ArgumentNullException as the exception that's thrown to avoid getting a NullReferenceException later. You should never explicitly throw a NullReferenceException yourself. Throw an ArgumentNullException instead.

So under what conditions is the NullReferenceException thrown? Usually, it's thrown when the developer is trying to access a method or a property of an instance of a class that is null. The following example demonstrates a NullReferenceException:

using System;

 

class Program

{

    static void Main(string[] args)

    {

        Widget widget = new Widget();

        Console.WriteLine(widget.Value);

        Console.ReadLine();

    }

}

 

public class Widget

{

    public string _value;

 

    public string Value

    {

        get { return _value.ToUpper(); }

        set { _value = value; }

    }

}


In this example, I'm creating a Widget class, but I never initialized the private field _value in the Widget. Unfortunately, the getter for the property Value tries to convert the _value to an upper case version of itself. It does this by calling "_value.ToUpper()". Because _value is null, a NullReferenceException is thrown, because the method cannot be called on an object set to null.

In some situations, it's a little more unclear as to what is null. This usually happens when there's alot of code compacted to one line. For example, take the following reflection code.

Widget widget = null;

string textValue = typeof(Widget).GetProperty("Text").GetValue(widget, null).ToString();

Console.ReadLine();


Now, you may initially think that the exception is thrown because the instance of Widget, widget is set to null, but that's not actually the reason it's thrown in this situation. Here, the NullReferenceException is actually thrown by the call to "GetValue", because the return of GetProperty happens to be null.

There are two ways I usually debug this particular error. The goal here is to find the null instance, so that code can be written to ensure it's value is set or to avoid it completely when it is null.

Debugging method 1: Use the ValueTips.

This works well for the first example, and in the situation where the object that is null is a property or field. To debug here, simply hover your mouse over the fields or properties in the line that is throwing the error, and if the value is null, you then know which value needs to be set, and you can take steps to resolve the issue. It looks something like this:



Debugging method 2: Use the Watch Window.

If you've never used the watch window, you should. It allows you to post most bits of code into a window, and have that code evaluated immediately. When the null object is returned from a method, this is the typically the best way to debug a null reference. The second example above is a great candidate for debugging this way.

First, open the watch window. There are four different instances of watch windows in Visual Studio. You can open any of them either from the menu (Debug -> Windows -> Watch -> Watch 1 through 4), or using the keyboard shortcut (Ctrl-Alt-W, followed by a number between 1 and 4).

Next, paste a portion of the offending code into the right portion of the watch window. Split apart the offending code by the "dots" that separate them. So, for instance, in the example above, I would first type in "typeof(Widget)" and see if that returns null. If it does not, I would then check "typeof(Widget).GetProperty("Text")", if that still returns a value, then I would check the next section, "typeof(Widget).GetProperty("Text").GetValue(widget, null)", and so on and so forth.

I've done this with the code above, and have found that GetProperty is returning null (apparently the property "Text" doesn't exist on a Widget), so I conclude that when GetValue is called, it's called on an object that is set to null, and thus I receive my NullReferenceException.



Come back on Wednesday, when we'll discuss NullReferenceException's big brother, ArgumentNullException.