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

September 29, 2007

Xml Code Snippets

A couple of months ago, I was giving a presentation about Web Services at the Portland Area Code Camp. The presentation was going okay, but I had the dreaded right-after-lunch time slot. The room was a little bit sleepy, to say the least. As I assembled a class, I typed prop and pressed tab twice. Studio diligently dropped a new property skeleton into my code. Suddenly, the room woke up. Everybody wanted to know what the cool add-in was that I was using, and where they could get it from. When I told them it was built into studio, they were elated. I don’t know if any of them remembered anything I had to say about Web Services, but I do know several of them went home and learned about snippets.

Xml Code Snippets are simply keyboard shortcuts for repetitive tasks that you may need to do in the IDE. If you open up the Studio IDE and select Edit–>Intellisense–>Insert Snippet (or press <ctrl>k – <crtl>x), a list of snippets available on the machine appear. Selecting prop, for example, from the list of available C# snippets creates a skeleton property, complete with member variable, into the class.

snippet.JPG

The property snippet highlights three values when dropped on the screen. The type of the property, the name of the property, and the name of the member variable. In the image above, myVar is highlighted. When I modify this variable name and tab off of it, the myVar in the getter and the setter will be updated automatically.

One of the neat things about Snippets is that you can create your own, or update the existing snippets. The included snippets are defined by default in %Program Files%\Microsoft Visual Studio 8\VC#\Snippets\1033\Visual C#. Modifying a snippet in this location will change the snippet for all users using the machine. Snippets can be modified for individual users by placing them in %MyDocuments%\Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets. You can also define your own locations for storing snippets in the Code Snippet Management Window (<ctrl>k – <ctrl>b).

I’ve updated the property code snippet on my machine to take care of a couple of annoyances that I run into when debugging.

First of all, if I’m debugging a method in which I’m passing several properties on an object as parameters, I always have to watch the IDE go down into the getter, and step through retrieving the member variable. Microsoft has given us the ability to automatically move over these steps by adding a DebuggerStepThrough attribute to our code.

Secondly, an object’s data is exposed via the property itself. I don’t need to see the internal variables displayed when I’m using the data tips window. Once again, Microsoft will let us do that with the DebuggerBrowsable attribute.

To update the code snippet on my machine, I simply do the following.

1. Copy the property snippet (prop.snippet) from the location under program files into the location under MyDocuments.
2. Open up the snippet. I’ll see that there are two major areas to the snippet itself. The <Header> element in the Xml provides information about the snippet, and how it will be accessed. The snippet element declares what values the snippet will collect, and how it will apply them.
3. Modify the CDATA section of the Code element to include my new debugger attributes. When I’m done updating, my new Code element appears as follows. (Note that I’m using the fully qualified names so that I don’t have to include System.Diagnostics in every scenario where I want to use my snippet.


<Code Language="csharp">
<![CDATA[[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private $type$ $field$;
 public $type$ $property$
 {
  [System.Diagnostics.DebuggerStepThrough]
  get { return $field$;}
  [System.Diagnostics.DebuggerStepThrough]
  set { $field$ = value;}
 }
 $end$]]>
</Code>

If I shut down and restart my browser at this point in time, my new snippet appears on the snippet menu.

Microsoft has released a lot of snippet add-ons for visual studio which can be found at http://msdn2.microsoft.com/en-us/vstudio/aa718338.aspx.

Code safe!

 MW

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.