March 04, 2009 Posted in programming  |  .net

Enforcing coding standards with Microsoft StyleCop

I can’t stress enough the importance of having a code convention in place before starting in any kind of software project.

What’s a code convention?

A code convention it’s about a team of developers agreeing on a standard csharpcodingstd way to statically structure the code that will be part of the system they are building together. Note that it doesn’t cover any aspect of the software design, (coupling, cohesion, dependency management and so on) but rather focuses exclusively on how the body of the code is organized.

You may wonder, how is this valuable? Well, a convention has one primary goal that goes beyond plain esthetic: to improve the code readability by achieving consistency. Following a common standard will make it easier for the members of a team to work on each other’s code without the burden of having to mentally adjust to different coding styles.

Style matters

A code convention apply to all kinds of programming elements such as declarations, expressions and statements and it usually covers different aspects. Here is a non-exclusive list of what could be described in a coding standard:

  • Naming (casing, use of prefixes/suffixes)
  • Ordering (where different members are defined in the context of a class)
  • Comments (where they should be placed and how they should be formatted)
  • Spacing (between various syntactic elements such as punctuation)

Now, making a group of developers agree on how they should format their code on such a level of detail isn’t the easiest thing in the world. We all see programming code as a way of express our minds, and that includes also how many spaces there are between the parenthesis in a method call and the list of arguments.

Verbal agreement is not enough

Even if you do succeed in finding a middle ground that makes everybody happy (or sort of), you still need to make sure that the team will stick to what has been agreed on, without relying on tedious manual code review. Luckily there are tools out there that can automatically check code against a predefined coding convention. StyleCop

One of them is StyleCop, a tool internally used by many teams at Microsoft, which has been repackaged and made freely available to the public under the Shared Source license.

The package contains a set of code format rules and a command-line program that checks all the source code files in a Visual Studio project against them and provides a compliance report. The rules that are included out-of-the-box are the lowest common denominator among different verbally defined coding standard used by many teams at Microsoft who are developing on the .NET platform using C#.

Here is a brief overview of StyleCop’s features:

  • Can only check C# code (support for other languages may be added in the future)
  • It integrates with Visual Studio and MSBuild, which makes it possible to run validations on demand from the IDE or as part of a build.
  • The set of rules to include can be controlled with a configuration file
  • Includes a graphic configuration editor (called StyleCopSettingsEditor)
  • It offers an SDK that allows to extend it by adding custom rules written as .NET classes 

As mentioned, StyleCop includes a Visual Studio add-on, which allows to run it at any point in time against the currently opened project from a menu item.

VSStyleCop

By default the results of the validation are reported back to the user as warnings, but you have the option to have them show up as errors, if you care enough about consistency that is.

VSStyleCopWarnings

Configuration can be controlled via a Settings.StyleCop file, which is easily edited with the accompanying GUI editor.

StyleCopConfigEditor

StyleCop can also be run through a set of MSBuild tasks. All you have to do is include the target file that invoke the proper tasks in your custom build definition or Visual Studio project file:

<Import
    Project="C:\Program Files\MSBuild\Microsoft\StyleCop\v4.3\Microsoft.StyleCop.targets" />

Resources

You can download the latest version of StyleCop from MSDN including documentation and samples. If you need more information, here you can find a good tutorial on how to successfully integrate StyleCop in your .NET project As of July 29, 2014 the tutorial is no longer available online.

/Enrico


February 25, 2009 Posted in programming

GDI memory leak in Windows Forms

A while ago I run into a rather interesting and insidious bug, which I thought I would share.

The scenario

We had a desktop application developed on the .NET Framework 2.0 using Windows Forms. Part of the requirements for this application was that the standard Windows controls had to be modified to have a custom appearance, to suite the customer’s needs. Since classes that are part of Windows Forms are really nothing more than thin winlogo managed wrappers around Windows’ graphic subsystem GDI, many customizations that required  the use of functions not directly exposed through .NET, forced us to invoke the Win32 API directly.

Now, for someone who has been developing on a virtual machine for a long time (whether it be the CLR or Java), commodities like garbage collection are quickly taken for granted. And when the time comes to step out of the safe and cozy managed world, it is easy to forget that those assumptions are no longer valid. And that’s where problems usually start. wpf

As a side note, if we were to build the same application today we would definitely choose Windows Presentation Foundation (WPF) over Windows Forms as UI technology,  since WPF allows to easily define the controls’ visual layout separately from their functionality without leaving the CLR.

The bug

Back to our case. Our Windows Forms application would run fine under normal operations, for about 3 hours until it suddenly crashed reporting a System.OutOfMemoryException (OOM). We also noticed that the application would survive for a shorter period of time if it was used more “intensively” (meaning opening and closing a lot of forms).

By looking at the log files we could determine that the exception was always originated from the constructor of a **Bitmap **object, which lead us to think that we were looking at a memory leak of some sort of unmanaged graphic resources. Like everything else in the System.Drawing and System.Windows.Forms namespaces, also the Bitmap class holds a reference to a corresponding GDI object, which is a resource allocated outside of the CLR and as such it must explicitly be released when no longer in use. Oddly enough, a through examination of the source code confirmed that all bitmap objects were correctly released from memory by calling the Dispose method on them. So what was leaking?

To further investigate exactly what was being used and left hanging around, we used a free tool called GDIUsage, which shows exactly how many and which kinds of GDI objects are being allocated by an application. On the left picture you can see how memory looked like at application startup compared to after a couple of minutes of normal usage.

The number of allocated GDI resources right after the application is launched The number of allocated GDI resources after using the application for a few minutes

It was apparent that we were creating an awful lot of font objects and forgetting to delete them! But why would it take a long time for the application to crash? Were we hitting some kind of threshold?

It turned out Windows puts a limit on the number of total GDI objects that can be created inside of a process. And that limit is exactly of 10.000 GDI objects in Windows XP. This means that allocating GDI object number 10.001 will always cause an error. You can use Task Manager to see how many GDI resources each process has currently allocated by selecting the GDI Objects column.

The total number of GDI resources allocated by the application as shown by Task Manager

The solution

At this point it was a matter of tracking down where in the source code we were creating System.Drawing.Font objects. Considering the rate of growth of these fonts instinct suggested it ought to be in some kind of global function that was being called from different places in the application. Here is what we found:

[DllImport("gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);

[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);

[DllImport("gdi32.dll", EntryPoint = "GetTextExtentPoint32A")]
private static extern bool GetTextExtentPoint32(
IntPtr hDC, string lpString, int cbString, ref SIZE lpSize);

[StructLayout(LayoutKind.Sequential)]
private struct SIZE
{
    int cx;
    int cy;
}

///
/// Gets the width and height of a string with the specified font.
///
/// The graphic context to measure the string.
/// The string to be measured.
/// The font used to display the string.
/// The size of the string in width and height.
public static SizeF MeasureString(Graphics g, string text, Font font)
{
    SIZE sz = new SIZE();
    IntPtr hdc = g.GetHdc();
    IntPtr prevFont = SelectObject(hdc, font.ToHfont());

    GetTextExtentPoint32(hdc, text, text.Length, ref sz);

    DeleteObject(SelectObject(hdc, font.ToHfont()));
    g.ReleaseHdc(hdc);

    return new SizeF((float)sz.cx, (float)sz.cy);
}

Sure enough the MeauseString method was being called from all over the application (don’t ask why). Do you notice anything particularly odd in the code? Let me show you the offending line:

// The Font.ToHFont() method creates a new Font GDI object
// whose reference is being passed as argument
// to the SelectObject Win32 function
// but is never explicitly deleted
IntPtr prevFont = SelectObject(hdc, font.ToHfont());

And here is how we fixed it:

public static SizeF MeasureString(Graphics g, string text, Font font)
{
    IntPtr hdc = IntPtr.Zero;
    IntPtr f = IntPtr.Zero;
    IntPtr prevFont = IntPtr.Zero;
    SIZE sz;

    try
    {
        sz = new SIZE();
        hdc = g.GetHdc();
        f = font.ToHfont();
        prevFont = SelectObject(hdc, f);
        GetTextExtentPoint32(hdc, text, text.Length, ref sz);
    }
    finally
    {
        DeleteObject(f);
        DeleteObject(prevFont);
        g.ReleaseHdc(hdc);
    }

    return new SizeF((float)sz.cx, (float)sz.cy);
}

As you can see we made sure the DeleteObject Win32 function is called to release the Font object created by the Font.ToHFont() method.

Lessons learned

So, what did we learn from this experience? We can summarize it in 3 rules of thumb when dealing with unmanaged code in .NET, whether it be Win32, COM, you name it:

  • Pay attention if any of unmanaged functions you are calling goes out and creates a new instance of some resource in memory. Carefully reading the specific API documentation is vital.
  • Every time you allocate memory it is your responsibility to explicitly free it when it is no longer needed by the program. No Garbage Collector will do this for you, you are on your own.
  • When creating a new unmanaged object, save a reference to it in a variable that you can use to reach that same object at a later time and remove it from memory. If you lose the reference before the object is explicitly destroyed, you have no way to reach that memory and it leaks.

I hope this rules will help you avoid some of the most common pitfalls leading to memory leaks in your own applications.

/Enrico


February 06, 2009 Posted in programming  |  .net

Managing shared cookies in WCF

Managing state across the HTTP protocol has always been one of the major challenges faced by developers when building applications on the web. Of course web services are no exception.

One way to overcome the stateless nature of HTTP without putting to much load on the web server, is to offload some of the information that has to be saved in the context of a particular conversation over to the client. The HTTP specification provides a native mechanism to do just that, by allowing web servers to bundle small pieces of textual data in a dedicated header of the response messages sent to the clients. These recognize the special payload, extract it, and store it in a local cache on disk to have it ready to be sent with every subsequent request. These small texts are technically known as “cookies”.

Cookies are opaque in ASMX

Cookies go back a long time in the history of HTTP, and have served the Internet (fairly) well so far. Sure they brought some serious security issues with them, but for the most part they have been a conventient way for developers of web sites/web  applications to save temporary pieces of information off the server and have it transparently sent back by the client with each request. This guarantee comes from the fact AsmxWs that every web browser on Earth has had the notion of cookies since web browser have had built-in support for cookies for the last 15 years or so.    

However, when it comes to web services, this assumption is no longer valid, since the client isn’t necessarily a web browser and doesn’t have to know how to handle cookies.

In the ASMX programming model, this problem has a quite simple solution. The client objects used to invoke operations on a web service can optionally reference an instance of a cookie container, were all cookies passed back by the web server are automatically stored and sent with each request.

using System.Net;

public class Program
{
    private static void Main(string[] args)
    {
        // Creates a new instance of a client proxy for an ASMX Web service
        MyWebServiceClient client = new MyWebServiceClient();

        // Creates the cookie container and assigns it to the proxy
        CookieContainer cookieJar = new CookieContainer();
        client.CookieContainer = cookieJar;

        // From now on cookies returned by any of the web service operations
        // are automatically handled by the proxy
        client.DoSomething();
    }
}

The advantage with this approach is that it is fairly opaque to the developer, which can inspect the contents of the cookie container at any time. As a bonus, it allows the same cookie container to easily be shared between multiple clients, enabling the scenarios when same cookie is required by multiple web services.

But they are transparent in WCF

In the WCF world, things are a little bit different. WCF, being a transport-agnostic technology, doesn’t allow the concept of a cookie to be directly reflected in the high level API, since it is specific to the HTTP protocol. This translate in practice in the web service client objects not having any CookieContainer property to set and retrieve.

However this isn’t necessarily a problem, since Microsoft did put a the possibility to enable automatic “behind the scenes” cookie management for HTTP clients. This of course is implemented at the WCF binding level, and can be switched on with a configuration setting:

<system.ServiceModel>
    <bindings>
        <basicHttpBinding allowCookies="true">
    </bindings>
    <client>
        <endpoint address="http://localhost/myservice"
                  binding="basicHttpBinding"
                  contract="IMyService" />
    </client>
</system.ServiceModel>

When this option is enabled the client will make sure all cookies received from a given web service are stored and properly sent on each subsequent request in a transparent fashion. But there is a catch: the cookie is only handled in the conversation with one web service. What if you need to send the same cookies to different web services?

Well, you’ll have to explicitly set the EnableCookies setting to false  (kind of counter-intuitive I know, but required nonetheless) and start managing the cookies yourself. Luckily, there are a couple of solutions.

If you wish to manually retrieve, store and send a the same given set of cookies from two different web service client objects in WCF, you could do this ad-hoc this way:

using System.ServiceModel;
using System.ServiceModel.Channels;

public class Program
{
    private static void Main(object[] args)
    {
        string sharedCookie;

        MyWebServiceClient client = new MyWebServiceClient();

        using (new OperationContextScope(client.InnerChannel))
        {
            client.DoSomething();

            // Extract the cookie embedded in the received web service response
            // and stores it locally
            HttpResponseMessageProperty response = (HttpResponseMessageProperty)
            OperationContext.Current.IncomingMessageProperties[
                HttpResponseMessageProperty.Name];
            sharedCookie = response.Headers["Set-Cookie"];
        }

        MyOtherWebServiceClient otherClient = new MyOtherWebServiceClient();

        using (new OperationContextScope(otherClient.InnerChannel))
        {
            // Embeds the extracted cookie in the next web service request
            // Note that we manually have to create the request object since
            // since it doesn't exist yet at this stage
            HttpRequestMessageProperty request = new HttpRequestMessageProperty();
            request.Headers["Cookie"] = sharedCookie;
            OperationContext.Current.OutgoingMessageProperties[
                HttpRequestMessageProperty.Name] = request;

            otherClient.DoSomethingElse();
        }
    }
}

Here we are interacting directly with the HTTP messages exchanged with the web services, reading and writing the cookies as a string in appropriate headers. In order to accomplish the task we need to use the “transport-agnostic” WCF API, which indeed makes the code more verbose compared with the ASMX example.

In situations were cookies must be managed in the same way for all web services invoked from a client applications, your best bet is to opt for a centralized solution by applying a very useful feature in WCF: message inspectors.

Message inspectors provide a hook in the WCF messaging pipeline offering the chance to look at and possibly modify all incoming or outgoing messages that transit on the server-side as well as on the client-side. The inspectors that are registered with the WCF runtime receive the messages before they are passed on to the application or sent to the wire, depending on whether it is an incoming or outgoing message.

WcfMessageInspectors

This way, it is possible to catch all HTTP responses coming from the web server, extract any cookies contained within the messages, and manually inject them in all subsequent HTTP requests on their way out. Here is a simplified view of the solution:

using System.ServiceModel;
using System.ServiceModel.Channels;

public class CookieManagerMessageInspector : IClientMessageInspector
{
    private string sharedCookie;

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        HttpResponseMessageProperty httpResponse =
            reply.Properties[HttpResponseMessageProperty.Name]
            as HttpResponseMessageProperty;

        if (httpResponse != null)
        {
            string cookie = httpResponse.Headers[HttpResponseHeader.SetCookie];

            if (!string.IsNullOrEmpty(cookie))
            {
                this.sharedCookie = cookie;
            }
        }
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        HttpRequestMessageProperty httpRequest;

        // The HTTP request object is made available in the outgoing message only
        // when the Visual Studio Debugger is attacched to the running process
        if (!request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
        {
            request.Properties.Add(
                HttpRequestMessageProperty.Name,
                new HttpRequestMessageProperty());
        }

        httpRequest = (HttpRequestMessageProperty)
            request.Properties[HttpRequestMessageProperty.Name];
        httpRequest.Headers.Add(HttpRequestHeader.Cookie, this.sharedCookie);

        return null;
    }
}

Message inspectors are enabled through the WCF extensibility mechanism called behaviors for single web service operations, entire web service contracts, or even specific endpoint URLs, depending on the scope the will operate in.

Here you can download a sample application showing how to implement a client-side message inspector to share the same cookies across multiple web services.

The WCF Cookie Manager sample application is also available on CodePlex. Thanks to Ray Dixon for creating the project.

/Enrico