Dot Net Thoughts

November 29, 2007

Debug and Release Builds

Filed under: csharp,Debugging,Uncategorized — dotnetthoughts @ 9:41 pm
Tags: , ,

Occassionally, I find old code concepts rattling around in my head that just don’t apply in today’s world. My most recent one was the difference between release and debug builds.

Back in VB6 days, one of the big reasons for creating a debug build was the generation of the pdb file. The pdb (portable database) file contained information about the names of items such as variables, classes and methods. Furthermore, it contained information about where these values were located in the code. Without the pdb file, all of this information was unavailable.

Imagine my surprise when I ran some code without a pdb file the other day, and I received a stack trace containing method names. With a little further thought, though, I realized it wasn’t that surprising. When disassembling a dll with ILDASM, I can see all of the method and variable names with or without a pdb file present. It turns out that the inclusion of a pdb file will allow you to trace a bug to a module and line number, but it is no longer needed for artifact names.

Release builds now contain pdb files by default. So what is the difference between the two build types? To help figure this out, I generated a very simple HelloWorld class and compiled it as both a release and a debug build. This class contained two methods.

       

        static void Main(string[] args) 
        { 
            Console.WriteLine(SayHello("Bob")); 
            Console.ReadLine(); 
        }               

        static string SayHello(string name) 
        { 
            return String.Format("Hello {0}!", name); 
        }       

Opening the Main method of the release dll in ILDasm yields a pretty straight forward implementation of the code. In the decompilation, you can see the creation of the string, the loading of the parameter, the string formatting, and the return of the value.

       

  .method private hidebysig static string 
          SayHello(string name) cil managed 
  { 
    // Code size       12 (0xc) 
    .maxstack  8 
    IL_0000:  ldstr      "Hello {0}!" 
    IL_0005:  ldarg.0 
    IL_0006:  call       string [mscorlib]System.String::Format(string, 
                                                                object) 
    IL_000b:  ret 
  } // end of method Program::SayHello       

The debug code looks almost exactly the same, but it includes a few differences to help assist in debugging. A local variable is initialized to hold the value of parameter so that it is available to a debugger. Also added are several nop (no operation) and a br_s (branch) method. These set points within the application on which a breakpoint can be set.

       

  .method private hidebysig static string 
          SayHello(string name) cil managed 
  { 
    // Code size       17 (0x11) 
    .maxstack  2 
    .locals init ([0] string CS$1$0000) 
    IL_0000:  nop 
    IL_0001:  ldstr      "Hello {0}!" 
    IL_0006:  ldarg.0 
    IL_0007:  call       string [mscorlib]System.String::Format(string, 
                                                                object) 
    IL_000c:  stloc.0 
    IL_000d:  br.s       IL_000f    IL_000f:  ldloc.0 
    IL_0010:  ret 
  } // end of method Program::SayHello       

I expected that tweaking the code to call a few subroutines would at least lead to some inlining optimizations within the IL. The differences between the Debug and Release versions of the IL were similar to those above. So where were the optimizations?

The only other major difference between the IL versions are the values stored in the DebuggingModes attribute. This attribute links back to the debug compilation flags that can be set when compiling a project. Since these are the only differences in the IL, the optimizations must occur within the JIT compiler itself. Scott Hanselman has an excellent post on compiled release and debug that is well worth reading.

That would be it for today! Good luck and code safe!

MW

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); 
        } 
    }

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(); 
    } 
}

September 15, 2007

Debugging – Data when you want it, how you want it.

Filed under: Debugging — dotnetthoughts @ 8:00 am
Tags: , , , , ,

One of the keys to debugging is being able to get fast access to the data you’re interested in. Anybody who has developed code for any length of time knows the pain of drilling down through objects in the watch window to find the one property that is buried seven layers deep. Fortunately, .Net gives us the ability to see summaries of object data when we are debugging. Two of the most useful features for creating and viewing these data summaries are theDebuggerDisplay attribute and Visualizers. Both of these add debugging capabilities to Visual Studio by allowing you to see subsets of data or reformatted data more easily.

To demonstrate how these work, I have created a quick-and-dirty application which you can download here. The solution contains three individual projects.

  • The Family project contains a simple data object which represents an individual family in a phone book application. The object contains a location to enter a last name and a phone number, as well as zero to many family members associated with it.
  • The FamilyVisualizer is an application we can use to visualize our code in a friendlier format than what .Net will be able to provide by default.
  • The FamilyApplication exists to load and process family data. In reality, we’ll just set a few breakpoints in this object and look at the results.

The first item we’ll take a look at is the DebuggerDisplay attribute. This is a very easy way to pull to the surface exactly what data you need to see in an object. If you look in the Family object, you will notice that the class is prefaced with this attribute:

[DebuggerDisplay("Last Name: {LastName}")]

When debugging code, this attribute will cause the last name of the user to be displayed when you hover over the variable. Note that you can still drill down into the object to see the child properties should you need.
visualizerimage1.gif

The DebuggerDisplay attribute is quite flexible, and will allow you to drill down in the object model, as well. For example, the following code displays the first child, assuming he exists.

[DebuggerDisplay("Last Name: {LastName} First Member: {FamilyMembers[0]}")]

The DebuggerDisplay is helpful from the standpoint of getting at data, but it isn’t so helpful in letting us visualize all of our individual family members. Since the FamilyMember property is one-to-many, we need a better way to display the individuals. This is where a custom visualizer comes in.

A custom visualizer is simply an object that extends the DialogDebuggerVisualizer and overrides the Show method. This allows you to use pretty much anything you can dream of to display data. If you look at the FamilyVisualizerDebuggerSide object in the sample code, you’ll note a couple of different things.

  • The class is marked with a DebuggerVisualizer attribute. This attribute contains information about what class is going to be used to present the visualizer (the FamilyVisualizerDebuggerSide), the type of object the visualizer is intended to display (the Family object), and a description for the debugger (Family Visualizer)
  • The project contains a form which we will use to customize our debugging display. It simply accepts data, and loads it into the appropriate labels and list boxes.
  • The class overrides the Show method, which will be used to display the debugger when debugging. Note that you must use windowService.ShowDialog to display the debugging form. (Calling familyForm.Show doesn’t work.)

If I copy my FamilyVisualizer dll into /MyDocuments/Visual Studio 2005/Visualizers and restart studio, I’m now able to access my visualizer directly from code that I have set a breakpoint on.

visualizerimage2.gif

Selecting the visualizer displays the windows form which we created to show our family data.

visualizerimage3.jpg

If you want help creating you own visualizer, Microsoft has a very good Visualizer Walkthrough you can use.

 There you have it. a couple of handy tricks in a nut shell. Good luck and code safe!

Mike

Blog at WordPress.com.