WinRT: reference count strikes back

At a first look WinRT objects look similar to .NET objects. In fact, WinRT supports many constructs we can found in the .NET framework: classes, methods, properties, delegates, events. But, under the hood, the model is completely different. In WinRT there is no managed runtime.

One of the differences that will the most painful, in my opinion, is that WinRT objects are not garbage collected. They are COM objects. They are reference counted; their lifespan is managed calling the old dear AddRef, Release and QueryInterface IUnknown functions.

Old-time COM developers remember that manually managing the calls to AddRef, Release and QueryInterface was no fun; COM rules could get very complicated, and smart pointers (like ATL CComPtr<>) were very handy, in most cases, to simplify the developer’s life.

The good news is that WinRT language projections take care to manage the reference count for us (as nicely as the old VB used to do). Normally, there should not be many reasons to call AddRef and Release explicitly.  But still, WinRT objects are not garbage collected. This makes a big difference: it is sometimes possible to have (kind of) memory leaks in .NET. But it is very easy  to have memory leaks in COM. What one needs to leak two objects is basically just a cross reference between them.

A small memory leak example

Look at the small class in Listing 1 as an example. The class WinRTComponent  exposes a single property, Ref, which can be set to a reference of another instance of WinRTComponent . Listing 2 shows the code of a client JavaScript app which references the WinRTComponent  project. When the web application is launched, every time the left button is clicked the function addAndLinkObjects  instantiates two instances of WinRTComponent  and sets cross references between them.

We can first run the application disabling the cross reference (commenting the line that sets the second reference: objB.ref = objA;). Once the JavaScript objects that “wrap” the WinRT objects go out of scope they can be deleted by the JS garbage collector. We don’t know when this deletion will happen; JavaScript uses its own garbage collection algorithm to decide when to destroy unreferenced objects. But the collection will certainly happen at least when the web application is being closed.

We can force the application to terminate with Alt+F4. Normally this causes the JS wrapper to release the last reference to the WinRT object, and have it destroyed too. This can be easily verified by setting a breakpoint in the class destructor.

But what happens if we uncomment the last line and set a cross-reference between the two WinRT objects? In this case the two WinRTComponent objects, cross referencing each other will still have the reference count to one and will stay alive forever. The destructor breakpoint will never get called. In other words, the objects will be leaked. (Not really forever, of course: their memory must be deallocated when the process terminates).

This memory leak pattern is quite bad, for two reasons:

  1. In a mobile/tablet environment memory is a scarce resource, so any memory leak should be avoided.
  2. If we use a RAII pattern and rely on the destructor to do some clean up (like closing a DB connection), the destructor could never be called.

In his //build/ talk on the internal details of C++ Metro apps Deon Brewis was mentioned using weak references as a possible way to avoid this kind of problems. Before the next post I’ll try to find out how we can use weak references to fix our WinRTComponent class.

Listing 1 – The WinRT object

#pragma once
#include <Windows.h>

using namespace Windows::Foundation;

namespace WinRTTest1
{
    public ref class WinRTComponent sealed
    {
        WinRTComponent^ _ref;

    public:
        WinRTComponent() {
            OutputDebugString(L"created\n");
        }
        ~WinRTComponent() {
            OutputDebugString(L"deleted\n");
        }

        property WinRTComponent^ Ref
        {
            WinRTComponent^ get() { return _ref; }
            void set(WinRTComponent^ propertyAValue) { _ref = propertyAValue; }
        }
    };
}
Listing 2 – The JavaScript client
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>WinWebApp1</title>
    <!-- WinJS references -->
    <link rel="stylesheet" href="/winjs/css/ui-dark.css" />
    <script src="/winjs/js/base.js"></script>
    <script src="/winjs/js/wwaapp.js"></script>
    <!-- WinWebApp1 references -->
    <link rel="stylesheet" href="/css/default.css" />
    <script src="/js/default.js"></script>
    <script>
        function addAndLinkObjects() {
            var objA = new WinRTTest1.WinRTComponent();
            var objB = new WinRTTest1.WinRTComponent();
            objA.ref = objB;
            //objB.ref = objA;
        }
    </script>
</head>
<body id="b" onclick ="addAndLinkObjects();">
</body>
</html>

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s