Dot Net Thoughts

October 27, 2007

Where Did My Exception Occur?

Filed under: Debugging — dotnetthoughts @ 7:19 am
Tags: , , , , ,

A couple of times a day, this blog takes a hit from someone trying to figure out how to programmatically determine on what line number an exception occurred. Determining this information actually turns out to be a fairly straight forward operation.

The one caveat for retrieving exception line numbers is that your application must have access to the portable database (pdb) file generated when the code is compiled. In C#, the default is to create this file for both a release and debug build. Unless you actively make a decision to exclude this file, you should be able to find it alongside your application or dll in your bin/<buildtype> directory.

The key to determining the line number on which an exception occurs is to check out the stack trace. A stack trace contains the history of all of the method calls made in your application up to a given point in time. If debug information exists, the stack trace can also display the file, module, and line number on which an exception occured. There are two ways to access the stack trace information:  a string directly from the exception, and StackTrace object from the System.Diagnostics namespace.

At the bottom of this post is sample code which accesses stack trace information directly from an exception object. The Main method calls GetValue. GetValue calls DivideByZero, which throws an exception. The exception is caught in the Divide method and is displayed on the console. When I run the code on my computer, the following stack trace is returned:


at System.Decimal.FCallDivide(Decimal& result, Decimal d1, Decimal d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at System.Decimal.op_Division(Decimal d1, Decimal d2)
at StackTrace.Program.Divide(Decimal a, Decimal b) in C:\DebuggingPresentation\StackTrace\StackTrace\Program.cs:line 36
at StackTrace.Program.GetValue() in C:\DebuggingPresentation\StackTrace\StackTrace\Program.cs:line 23

This StackTrace contains a snapshot of my application at the point in time the error occured. The most recent call exists at the top of the stack. Reading from the bottom up, we can see that GetValue (line 23) called Divide (line 36). Our application triggered three method calls into the Decimal object, itself.

Viewing the stack trace string directly from an Exception object has a couple of drawbacks. For starters, we can only see the stack trace to the point in time that the exception was handled in our code. The stack trace does not show that Main initially called GetValue(). In our application, this is trivial to figure out, but if GetValue() can be called from multiple methods, we may want to be able to see higher up the stack. Also, we may want to persist our exception information by file, module and line number. We could probably come up with some crazy regular expression to pull this information out, but it wouldn’t be much fun to say the least.

The StackTrace object in the System.Diagnostics namespace allows us to see the entire stack trace above an exception when it occurs. Let’s modify the code in the Catch block to use a StackTrace object. The ‘true’ parameter indicates that we do want access to the file name, module name, and line number.

catch (DivideByZeroException ex) 
{ 
   System.Diagnostics.StackTrace st = 
      new System.Diagnostics.StackTrace(true); 

   result = st.ToString(); 
}

When we call the ToString() method of this StackTrace object, we now get to see the entire stack up to the point the exception was handled.


at StackTrace.Program.GetValue() in C:\DebuggingPresentation\StackTrace\StackTrace\Program.cs:line 29
at StackTrace.Program.Main(String[] args) in C:\DebuggingPresentation\StackTrace\StackTrace\Program.cs:line 15
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile,
Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

If we want to pull out line or module information on a specific frame, we can iterate over the Frames object exposed by the stack trace. If we tweak the Catch block one more time, we can see how we can pull out individual pieces of data. This could potentially be used to automatically log our exceptions to a database should a problem occur. Note that in this example, I’m going to pass in my exception to the constructor of the StackTrace object, indicating that I want to take a look at the StackTrace of this particular exception.

catch (DivideByZeroException ex) 
{ 
   StringBuilder sb = new StringBuilder(); 
   System.Diagnostics.StackTrace st = 
      new System.Diagnostics.StackTrace(ex, true);     

   foreach (System.Diagnostics.StackFrame frame in st.GetFrames()) 
   { 
       sb.AppendLine( frame.GetFileName() + ": " + 
         frame.GetMethod() + ": " + frame.GetFileLineNumber()); 
    } 
    result = sb.ToString(); 
}

Using this code gives me my “custom” Stack trace information.


: Void FCallDivide(System.Decimal ByRef, System.Decimal, System.Decimal): 0
: System.Decimal Divide(System.Decimal, System.Decimal): 0
: System.Decimal op_Division(System.Decimal, System.Decimal): 0
C:\DebuggingPresentation\StackTrace\StackTrace\Program.cs: System.Decimal Divide(System.Decimal, System.Decimal): 45
C:\DebuggingPresentation\StackTrace\StackTrace\Program.cs: System.String GetValue(): 25

So, there you have it. A fairly simple way to get your error line numbers! Good luck with it, and code safe!

Mike

——————-Sample Code here!——————————————–

    class Program 
    { 
        static void Main(string[] args) 
        { 
            Console.WriteLine(GetValue()); 
            Console.ReadLine(); 
        }          

        static string GetValue() 
        { 
            string result = String.Empty;          

            try 
            { 
                result = Divide(3M, 0M).ToString(); 
            } 
            catch (DivideByZeroException ex) 
            { 
               result = ex.StackTrace; 
            }          

            return result; 
        }          

        static decimal Divide(decimal a, decimal b) 
        { 
            return (a / b); 
        } 
    }

Advertisements

October 20, 2007

Doubles, Decimals, and Dividing by Zero

Filed under: Misc Thoughts — dotnetthoughts @ 7:02 am
Tags: , , , , , , , ,

“.Net Exception Divide by zero” often comes up as a search criteria when this blog is hit. (I use division by zero a lot when I’m writing about errors and exception handling. It’s easy to create, and it’s easy to understand.) I couldn’t quite figure out exactly why anybody would be querying on it directly. I think I’ve figured it out, though.

Last week, I was typing up a division example for the blog. For whatever reason, I used double instead of decimal for my input parameters and return value.

   private static double Divide(double i, double j) 
      { 
         return (i / j); 
      }

When I passed in values of 5 and 0 for this method, I was expecting a divide by zero exception. Instead, my console app ran just fine and printed the word Infinity on my screen. I was totally caught off guard by this result. If you pull out an old calculus book, you’ll find that mathematicians often will say that the value of 1/x, as x approaches 0, is infinity (a standard limit), but that 1/0 is undefined. (You can’t take one object and break it into groups of zero.)

When I run the same code above using decimals, instead of doubles, I get a divide by zero exception. This is what I would expect.

With a little bit of thought and poking around, I think that there is a method behind the madness.

Doubles are floating point types. These types are specifically engineered never to throw an exception. Instead, they return values such as infinity, positive infinity, negative infinity, and not a number. Why?

I suspect that the reason has to do with precision. The double type supports numbers as small as +-5*10-324 and as large as +-1.7*10308. Its precision, however is only 15 to 16 digits. Due to the way that floating points are handled, you can’t ever be totally sure exactly what value your Double contains for very large or small numbers. For example, the following code prints out a value of 9.99988867182683E-321 in my output window when I run it:

   private static void DoublePrecision()  
   { 
       double double1 = 1 * Math.Pow((double)10, (double)-320); 
       Trace.WriteLine("double1: " + double1.ToString()); 
   }

This loss of precision means that the compiler itself can’t determine whether a value truly is zero, or if it is a really small number quite close to zero. Mathematically, 1/(10-324)2 is 1/10-648. If the first equation were plugged into .Net, the the result wouldn’t be infinity, but it would be greater than the double can deal with. The convention seems to be to return infinity for my initial divide by zero question.

Decimals, on the other hand, support numbers as small as +-1*10-28 and as large as +-7.9*1028. A decimal’s precision is 28 to 29 significant digits. Since the precision is equal to the exponential power of the range supported, the compiler knows the value it holds in the register is accurate, at least to defined precision. If it thinks it has a zero, it actually has a zero, and can safely throw a DivideByZero error if you try to use it to divide. This added precision is why Microsoft encourages decimals for financial and scientific values.

I’m making some educated guesses behind the thinking of the writers of the IEEE 754 standard, which defines floating types, but I don’t suspect I’m too far off. Let me know if you have any insights!

Good luck and code safe!

Mike

October 12, 2007

Why Language is Important (Why I prefer C#)

Filed under: Debugging,Misc Thoughts — dotnetthoughts @ 7:13 pm
Tags: , , , , , , ,

How many times have you heard this statement?

 “It doesn’t really matter whether you choose Visual Basic.Net or C#. It all compiles down to the CLR, anyway.”

This statement makes me shudder. It’s at least partially true. All managed code does compile down into the common language runtime. This is what allows us to mix and match components written in different languages when building an application. What this statement doesn’t recognize is the fact that every language was created for a specific purpose.

In his book CLR via C#, Jeffrey Richter lists around two dozen different compilers he knows of. These include many well known languages such as C#, J#, LISP, Perl, and Eiffel, just to name a few. Having this many different compilers would be a lot of wasted effort if each language acted exactly the same as every other language out there.

The reality is that each language has its advantages and disadvantages. C# and VB.Net are great for handling Input and Output. APL is optimized for mathematics and finance. PERL is a monster when it comes to string manipulation. LISP, one of the oldest programming languages, is still the language of choice for AI. C++.Net allows both managed and unmanaged code to run within the same module. Every language is designed for a specific type of development.

I would love to learn the ins and outs of all the different languages out there. When working as a consultant, however, reality dictates that I will almost always be programming either C# or Visual Basic.Net.

Choosing between these two isn’t always an easy decision. In many ways, I find the UI presented by the Visual Basic team to be superior to the UI offered by C#. Filtering down methods and properties to those most used, the my namespace, and better on-the-fly error detection make Visual Basic.Net a very enjoyable programming experience. When I’m in the IDE, I feel that VB wins hands down.

Ultimately, though, when I look at the intent of the entire language (and not just the UI), VB loses some of its shine. The intent of the C# language was to build a clean and new language around the .Net runtime. C# has a clean mapping between .Net runtime capabilities and features. Close alignment with the framework was its intent. VB, on the other hand, was designed to maintain market share by retaining much of the language from the previous version of VB. This often did not make sense in the context of the new .Net environment.

Let me give you an example. In legacy VB days, there was no such thing as structured exception handling. All errors were handled either by calling On Error Goto <label>, or by calling On Error Resume Next. On Error Goto isn’t a particularily good way to handle errors. On Error Resume Next is a disaster. Take this code, for example:

  Sub ResumeNextTest()
     On Error Resume Next
     Dim xml As XmlDocument = New XmlDocument
     xml.Load("c:\AMissingFileName.xml")
     Console.WriteLine(xml.OuterXml)
     Console.WriteLine("ResumeNext complete.")
  End Sub

If the attempt to load the xml fails, there will be no indication. You could probably infer that the xml didn’t load when the Console prints out nothing on the next line, but there is no explicit indication. In this example, the Xml data is accessed right away. In a more complex app, though, the problem of the missing Xml data may not show up for quite some time.

The .Net runtime has no concept of On Error Resume Next, though. If an error is thrown, something has to happen. How does VB get around this?

To find out, I wrote a simple Console App with the above method included, and ran reflector against it to see what the VB compiler did when it converted the code to IL. (I’ve included the converted code at the bottom of this post.) Essentially, VB wraps the entire On Error Resume Next method in a try-catch block. As it progresses through the code, the CurrentStatement variable is updated to indicate the location in the code. Should an exception occur, the exception is swallowed, and the user is redirected to the label following the point that the trouble happened.

While this is a clever way of solving the problem, it allows a very dangerous practice that should have been eliminated to carry on. Furthermore, if I ever had a developer present me with this kind of spaghetti code during a code review, we would have to have a serious talk.

Your choice of VB, C#, or any other compiler is up to you. Be sure you know the pros and cons of whatever language before you develop with it, though.

Good luck and code safe!

 Mike

public static void ResumeNextTest() 
{ 
    // This item is obfuscated and can not be translated. 
    int VB$ResumeTarget; 
    try 
    { 
        int VB$CurrentStatement; 
    Label_0001: 
        ProjectData.ClearProjectError(); 
        int VB$ActiveHandler = -2; 
    Label_0009: 
        VB$CurrentStatement = 2; 
        XmlDocument xml = new XmlDocument(); 
    Label_0011: 
        VB$CurrentStatement = 3; 
        xml.Load(@"c:\AMissingFileName.xml"); 
        goto Label_0089; 
    Label_0024: 
        VB$ResumeTarget = 0; 
        switch ((VB$ResumeTarget + 1)) 
        { 
            case 1: 
                goto Label_0001;   

            case 2: 
                goto Label_0009;   

            case 3: 
                goto Label_0011;   

            case 4: 
                goto Label_0089;   

            default: 
                goto Label_007E; 
        } 
    Label_0044: 
        VB$ResumeTarget = VB$CurrentStatement; 
        switch (((VB$ActiveHandler > -2) ? VB$ActiveHandler : 1)) 
        { 
            case 0: 
                goto Label_007E;   

            case 1: 
                goto Label_0024; 
        } 
    } 
    catch (object obj1) when (?) 
    { 
        ProjectData.SetProjectError((Exception) obj1); 
        goto Label_0044; 
    } 
Label_007E: 
    throw ProjectData.CreateProjectError(-2146828237); 
Label_0089: 
    if (VB$ResumeTarget != 0) 
    { 
        ProjectData.ClearProjectError(); 
    } 
}

October 6, 2007

My experience with paired programming

Filed under: Management — dotnetthoughts @ 7:08 am
Tags: , , ,

I’ve spent the better part of the morning trying to get my first WCF code sample to work. I got it to work eventually, but it took quite a bit more time than I was expecting. Instead of writing new code this week, I thought I’d record some of my recent experiences with paired programming.

Paired programming is simply placing two developers at a single workstation to write code. The thought process is that two heads approaching the same problem will have different experiences and perspectives on how to tackle it. While one person is writing code, the other is supposed to be thinking about the unit test and how the code might break. The philosophy recommends switching developers at the keyboard several times during the day. Research indicates that the total time to develop a system using the paired technique is relatively close to the same amount of time required for developers working individually. Code quality, however, improves greatly.

I’ve recently been working on a project with some pretty complex algorithmic calculations. I’ve been pairing with an architect for about four months, and I’ve come up with these thoughts for anybody considering pairing.

  1. Make sure you have a good personality match. The paired developers are going to be spending a lot of time in a small space together. My partner and I get along extremely well together, but there are still days where we want to throw each other out the window. If there are personality conflicts between the developers, they will probably be magnified significantly. Learn the strengths and weaknesses of your partner, and play to each others strengths as much as possible.
  2. Be flexible with the philosophy. True paired programming requires that both developers be there for each and every line of code that is written. Some teams may find that to be critical to their development process. We’ve fallen into a pattern of coding difficult sections paired, and easier secitons individually.
  3. It’s not called trio programming for a reason. Early on in the project, we had a third team member working on the same code we were working on. When any two of us were working together, it was a very clean, efficient day. When all three of us were in the room together, the additional voice added just enough chaos that our productivity fell significantly.
  4. Be prepared to defend your point of view. Typically, when my paired developer and I both have a conflict over the right way to do something, we will debate back and forth for awhile. It often turns out that both of our initial thoughts were wrong and we end up with a far superior way of solving the problem. Both team members must be willing to give and take on what the final code looks like. If one personality dominates, I think a lot of the benefit would be lost.
  5. Team programming is a good way to build team cohesion and consistency.When starting my last project, an entirely new team was brought on. We spent the entire first month, “team developing” our first module of code. This brought all of our coding standards in line with each other, and helped develop relationships very quickly.
  6. Try to keep ability levels similar. Mentoring is often talked about as one of the advantages of paired programming, and two developers can learn a lot from each other. I would advise caution when pairing two programmers together where one is significantly more senior than the other. The risk is that the junior programmer be overwhelmed or intimidated by the senior programmer, while the senior is frustrated with the development speed and thought process.
  7. Understand the effects of scheduling. If you are a shop that adheres 100% to the philosophy that both programmers need to be present for work to get done, you will have to have a plan for how to deal with sick days, vacations, doctor’s appointments, etc. This is one of the big reasons I recommend flexibility with the philosophy.
  8. Finally, keep a sense of humor. The world can start looking a little strange after being trapped in a room with the same person for hours on end. Enjoy the friendship and the development.

That’s all for today. Code safe!

 MW

Blog at WordPress.com.