.net

WinDBG Tips

I had previously blogged about finding some good tutorials on how to get started. I’ve been using the WinDBG debugger a little bit more lately and I’ve put together a “cheat sheet” that I use for the most common commands and I thought I would share them. Almost all of these commands are specific to the SOS extension to debug .NET code.

If you are a seasoned WinDBG user, you’ll know all of these command by heart, but if you are just getting started this might help. The first thing to do is run, don’t walk to setup your “Symbol Search Path” setting. Enter CTRL+S from inside WinDBG, mine looks like this:

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

You can find out more about it in this Microsoft support article.

The WinDBG command line has TAB completion, so when you type the first few characters of a command, hit TAB to cycle through the possible completions.

I have picked up the majority of these tips by reading some of the great blogs on MSDN. If you are interested in learning a lot more about WinDBG and how to debug some very difficult problems you need to subscribe to Tess’s blog right away!

If you know of any other tips or helpful WinDBG command, please post them in the comments and I’ll add them to the list.

 

Command Description
.loadby sos mscorwks Loads the correct version of the SOS(.NET) extension dll based on the version of mscorwks currently loaded
.chain View the currently loaded extensions
.hh command Opens the help file for the specified command. For example: .hh ~
!help Displays help for extensions, including for SOS a list of commands
!help command Displays help for the specified extension command. For example: !help clrstack
.cls Clears the sceen
~ List all threads
!threads List managed threads
~# s Set current thread, where # is a thread number, for example: ~3 s
!clrstack Display the CLR stack
!clrstack Display the CLR stack with parameters
kb Display the stack frame for the native thread
!dso Dump objects on the stack
!do Dump managed object
dc Display the contents of memory as DWORDS and ASCII chars
!dumpheap Dumps the contents of the managed heap
!dumpheap -stat Display stat summary of managed heap
!dumpmt address Dumps the MethodTable of the specified address
!dumpmt -md address Dumps the MethodTable of the specified address and displays a list of all the methods on the object
!dumpclass address Displays the EEClass for the specified address
!dumpobj address Display the details of the object at the specified address
!eestack Runs !DumpStack on all threads
!dumpruntimetypes Displays all System.RuntimeType object from the managed heap
!runaway Displays thread time statistics
.time Displays System Uptime, Process Uptime, Kernel Time and User Time
!syncblk Displays synchronization lock info
!dumpheap -thinlock Displays objects locked with thinlocks instead of syncblk’s
!dumpheap -type System.String -stat Displays count and total size of the specified type (in this case System.String) on the heap
!address Display virtual memory stats, load addresses and reserve/commit info
!address -summary Display just the summary virtual memory info
!eeheap -gc Display garbage collector generation info
!pe Print exception details
~*kb Display callstacks for all threads
!finalizequeue Display stats and contents of the finalizer queue

c#
.net
programming

Comments (0)

Permalink

Fun with GC.SuppressFinalize

While discussing some code with a colleague, I ran across an unexpected behavior of GC.SuppressFinalize. I’ve put together a small sample for our discussion.

 


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    public class Base
    {
        ~Base()
        {
            Console.WriteLine(“Base Finalizer called”);
        }
    }

    public class Derived : Base
    {
        ~Derived()
        {
            Console.WriteLine(“Derived Finalizer called”);
        }

        public void Suppress()
        {
            GC.SuppressFinalize(this);
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Derived d = new Derived();
            d.Suppress();

            Console.ReadLine();
        }
    }
}

Okay, so what gets printed out at the console?

Actually, nothing.

It was a little surprising to me at first, especially since after years of C++ programming the ~ immediately invokes destructor semantics in my head. I worked through a number of different variations, but I always got the same result. I used the !FinalizeQueue command available in the SOS extension of WinDBG to verify that there was only the Derived class reference on the queue. So when you say, SuppressFinalize(this) you really mean it! 

Now, granted, this is a cheesy example. But the discussion came up when talking about the correct way to implement IDisposable. In the example provided, SuppressFinalize(this) is called in the Dispose method. Now that’s a good thing, because you want to prevent the call to the finalizer since you have already cleaned up any resources via your Dispose implementation. But, what happens if a class you derived from, either your own or a third party, does not implement IDisposable and instead is relying on the finalizer? Or they do implement IDisposable but somewhere else along the virtual method override chain someone forgot to call the base class implementation.

This really never should be a problem if your code implements the IDisposable interface correctly. And since implementing a Finalizer on your class has a negative performance impact you should only use them when you really need to. Anyway, this makes a great conversation at any nerd party :-)

c#
.net
programming

Comments (0)

Permalink

Visual Studio Keyboard Tip #7 - Incremental Search

The Visual Studio editor has a very useful incremental search feature built in. Let’s try it out.

  • Create a new Windows Application project.
  • Open up the Form1.Designer.cs file in the editor.
  • CTRL + I (this activates Incremental search mode)
  • Type: “disp” (without the quotes)
  • The selection should have moved to the first match of “disp” in the file.
  • Type CTRL + I again. This moves you to the next match.
  • CTRL + SHIFT + I moves you to the previous match.
  • BACKSPACE removes the last character from the search string.
  • ESC cancels incremental search mode.

visual studio
keyboard
c#
.net

Comments (0)

Permalink

ScottGu’s ASP.NET 2.0 Tips/Tricks TechEd Talk Posted

If you develop with ASP.NET you need to subscribe to Scott Guthrie’s blog.

His blog is full of detailed and well written articles that provide invaluable insight to any ASP.NET programmer.

He just posted the PowerPoint presentation and the sample code from his TechEd talk. I would highly recommend you download and review the sample project. I know every time I download samples that Scott has posted I learn something new.

Some of the features shown:

  • app_offline.htm
  • cross page postbacks
  • maintaining scrollback position
  • default button
  • custom databinding expressions

visual studio
c#
.net

Comments (0)

Permalink

C++/CLI Interop Examples

If you work with managed/native code interop you should read this blog post series {Part 1 & Part 2} by BorisJ who is a Visual C++ Program Manager at Microsoft.

He provides good examples and clear explanations of some C++ interop scenarios.

 

c#
.net

Comments (0)

Permalink

C# WeakReference Example

How would you like to be able to write the programming equivalent of “I might need this later….but I’m not so sure”? I’ll show you how.

A WeakReference is an object with a very interesting behavior, it allows you to keep a reference to an object while still making it possible for it to be garbage collected. See a previous post for a little more detail and links. Internally the WeakReference type uses an IntPtr to track a GCHandle that was acquired using the GCHandleType of Weak or WeakTrackResurrection.

This can be very useful if you are trying to managing the lifetime of objects in a cache or adding optimizations to possibly save time by not having to recreate an expensive object.

Let’s look at an example.

In your class you created two member variables:

WeakReference _weakRef = null;

Person _strongRef = null;

You created two new Person objects (which are simple objects I just created for this example, consisting of a Name property and some reference tracking code). Next you set the member variables to the newly created instances of the Person objects.

_strongRef = p;

_weakRef = new WeakReference(p1);

The difference here you’ll notice that _strongRef is just a regular normal reference, whereas _weakRef is set to a WeakReference object with the person object (p1) passed in as a parameter in the constructor.

If a garbage collection were to occur, or just for testing purposes you called it yourself with:

GC.Collect();

Then the p1 target object that is held by the _weakRef member variable should be garbage collected. You can write code to check:

if (_weakRef.IsAlive)

If the WeakReference is still alive you can convert the WeakReference to a strong or normal reference by using code like this:

Person p = _weakRef.Target as Person;

Now the p reference is treated as a strong reference and won’t be collected until it is no longer used. If you wanted to keep the reference around after the scope you could set that to a member variable.

There aren’t many times in programming that you get to say “maybe”. It’s usually binary — 1 or 0. A WeakReference seems to be one of them.

 

c#
.net

Comments (4)

Permalink

Ruby On Rails Blog Written by .NET Developers

I found a very interesting blog called “Softies On Rails” that is written by two developers who have spent a lot of time developing software using Microsoft .NET.

Here are a few of my favorite posts on their blog:

Rails IDE for Windows after reading this post I downloaded the IDE and it’s like a mini version of Visual Studio just for Ruby On Rails — pretty cool.

Ruby 101: It’s a script

.NET to Rails Survival Guide

Why Rails? Part 3: Ruby

Why Rails? Part 5: Because I can test it

Overall a very interesting blog. Subscribed! And good luck with your new venture guys!

blog
.net
ruby
rails

Comments (0)

Permalink

RubyCLR

If you have ready my previous posts you know I am learning the Ruby language and the Rails web application framework.

I saw this post on blogs.msdn.com by Tim Ng that provides details on using RubyCLR to call VB.NET methods from Ruby which seems pretty straightforward and calling Ruby from VB.NET which is more complex.

Between the IronPython project and now RubyCLR it open’s up some interesting possibilities for using the power of dynamic languages in .NET.

.net
ruby

Comments (0)

Permalink

Really powerful debugging with WinDBG & SOS.dll

If you have never used WinDBG or the SOS extensions before, read the following blog posts by Mike Taulty:

Mike walks you through a sample debugging session with WinDBG. Then in the second part, he focuses on the SOS extensions for .NET debugging. With the SOS extension you can do some seriously cool stuff:

  • View thread/threadpool info
  • View the finalizequeue
  • See what’s allocated on the managed heap
  • Determine what is keeping your managed object from being finalized by viewing it’s “roots”

If you have Visual C++ installed you can actually use SOS calls from the Visual Studio debugger! Read Mike’s post, that walks you through the setup and use of SOS from inside Visual Studio. As Mike points out, make sure you go to the project properties, choose Debug, and then check “Enabled unmanaged code debugging”. Be prepared the very first time you do this, it might be slow because the symbols have to be downloaded/loaded.

windows
tools
c#
.net

Comments (0)

Permalink

Team Foundation Server Project Guidance

Eric Lee’s blog post provides some guidance into how Microsoft sets up the Areas for a Team Project in Visual Studio Team System.

I know this has been a source of a little bit of confusion for TFS users, so it’s nice to see an example of how Microsoft is using the feature internally.

Thanks for the post Eric, would it be possible for you to show us an example of how you setup the Iteration tab too?

visual studio
c#
.net
tfs

Comments (0)

Permalink