July 2005 - Posts

No PDC This Year!

Don’t worry. Before you cancel your hotel reservations, the PDC is by no means cancelled!

I will however not be able to attend this year. Financial pressure has gotten in the way. (I hope you have a great time Ari, but you really need to get your blog fixed so you can blog your way through the conference.)

I will however be at the MVP Summit and am looking forward to meeting many of you. Let me know if you’re planning on being there. It will be great to meet some of the folks behind the blogs and all the other great people I've been in contact with but have yet to meet.


© 2005 Kenny Kerr

Posted by KennyKerr with 2 comment(s)

Mixed Types and Finalization

After I wrote about Mixing Native and Managed Types in C++ I received some feedback that my AutoPtr ref class really needs a finalizer. I had hoped to leave a discussion of finalizers to another day but since you insist…

:)

To fully appreciate the state of resource management in Visual C++ 2005 you need to understand the history and reasoning for why the CLR does not provide deterministic finalization. Brian Harry wrote an excellent post on this topic back in October 2000. If, like me, you spent many blessed hours in the 90s basking in the glory that is apartments, contexts, threading models and IUnknown, then you should appreciate this. He also has a blog but he didn’t get far with that. Here’s hoping he’ll blog some more!

“I am convinced that substantial programs can be reasonably written and debugged without the system providing any automatic support.  That said, I fully agree that it would be better if the system/language provided additional support.  Without it, you must build the behavior into the contract of the objects (like calling the Dispose method).”

The good news is that although the system, in other words the CLR, does not provide any automatic support, Visual C++ 2005 does provide language support for deterministic finalization in the form of C++ destructors that implement the Dispose pattern, although lets hope we can get this bug fixed soon! You can read my MSDN article for an introduction to C++/CLI and how memory and resource management are represented in Visual C++ 2005.

CLR reference types (called ref classes in C++) may provide an implementation of the IDisposable interface to indicate to callers that instances may be holding onto resources that need to be released deterministically. CLR reference types authored in C++ can provide an implementation of the Dispose pattern simply by providing a destructor. C++ also hides the call to the Dispose method behind stack semantics for local variables, automatic destruction of member variables and operator delete for handles.

So what are finalizers for? Finalizers provide a final safety net for objects whose Dispose method was not called. Think of it as an added layer of defense in the pursuit of more robust applications that can run longer without locking up system resources or running out of memory. If you are a C++ programmer this may sound very much like compensating for sloppy programming. Admittedly this is a bit harsh, but having finalizers release resources like file handles and database connections can adversely affect the user experience and create very badly behaving programs.

As I write my own applications, I consider failure to dispose of a managed object to be the same as failure to delete a native object, so using a finalizer does not come into play since I would just be compensating for a bug in my code. Finalizers also come with relatively significant costs at runtime. Besides their non-deterministic nature, every object with a finalizer uses up additional resources as the CLR needs to track finalizable objects. Even suppressing finalization (which C# programmers can do programmatically with the GC.SuppressFinalize method and C++ programmers get for free from the compiler) doesn’t mitigate this cost. It merely reduces the likelihood of the finalizer being run.

Another problem with finalizers that is often overlooked is related to their non-deterministic nature. The CLR runs finalizers on a background thread (and likely multiple threads in future versions of the CLR). Most developers assume this will occur some time after the object “goes out of scope”. In fact the CLR is free to aggressively finalize an object before the object’s last method call has completed forcing thread synchronization to be employed in some cases.

Writing code that will be used by others deserves extra care however. Developers writing libraries should account for the fact that applications may be written that don’t dispose/delete library objects and finalizers can help to provide this safety net. This can be especially important for resources that the operating does not automatically reclaim when a process terminates and, in the case of hosting environments, when an app domain is unloaded.

Certainly there are other improvements that can be made to AutoPtr. One potentially significant problem is that the CLR is not aware of the memory cost of the native object. It only sees a native pointer (either 4 or 8 bytes depending on platform) and so this really doesn’t help the CLR in determining whether or not there is in fact sufficient memory pressure to warrant a garbage collection. Version 2.0 of the .NET Framework provides a way of giving the CLR the hints necessary to make an informed decision. The AutoPtr class could for example use the AddMemoryPressure and RemoveMemoryPressure static methods from the GC class to inform the CLR of the size of memory used by the native object.

Here are some additional resources that you may find helpful:

Brandon Bray just wrote a discussion of mixed types and referred to my original post on mixing native and managed types.

Chris Brumme’s blog also has a lot of great posts if you’re looking for further insight into the design of the CLR.

Joe Duffy posted an article on the Dispose pattern and finalization which includes annotations from a number of the CLR architects.


© 2005 Kenny Kerr

Posted by KennyKerr with 4 comment(s)
Filed under: ,

Adam on Compiling MSIL

Adam White, a friend of mine from Toronto, read my Introduction to MSIL series and noticed that I neglected to provide any information on how to actually compile all the IL that I wrote about. I figured it just wasn’t all that interesting, but if you have read my series and need a bit of help getting some of the examples to run, you may want to check out Adam’s post where he provides some helpful information.

Keep in mind that some of my samples assume version 2.0 of the .NET Framework so be sure to use the 2.0 version of ILASM.

Another useful tool when working with IL directly is the CLR Debugger which allows you to step through IL line by line. Be sure to specify the /debug option with ILASM to include debug information if you wish to use the debugger.


© 2005 Kenny Kerr

Posted by KennyKerr with no comments
Filed under:

Moving to Visual C++ 2005 July CTP

I just installed the July CTP of Visual Studio and immediately noticed a bug in the way the Visual C++ compiler implements the Dispose pattern for ref class destructors.

I logged a bug and you can read about it here.

Anyway, just thought I’d mention it in case you’re considering moving from Beta 2.


© 2005 Kenny Kerr

Posted by KennyKerr with 2 comment(s)
Filed under:

Mixing Native and Managed Types in C++

Wow, its turning into a busy month. I just haven’t had any time to blog despite having a number of interesting topics to cover. I’ll try to get a few of them written soon. Here’s a topic from one of my regular readers.

The CLR naturally supports mixing managed and native method calls allowing you to easily call native functions from managed functions (which are of course natively compiled before execution) and visa versa. This is all largely transparent in C++. What’s not as transparent is how to mix managed and native types. The reason is that there is a greater distinction between native and managed types compared with function calls. Beside obvious differences such as those introduced by different calling conventions and virtual invocation, function calls aren’t all that different. Types however require a bit more help from the programmer/compiler since native and managed types can have very different characteristics. This is very evident in C# as you often need to decorate native type definitions with all kinds of attributes to control memory layout and marshalling. Fortunately for the C++ programmer the compiler takes care of much of this when you define or include native type definitions such as those found in the various Windows header files, but the programmer is still responsible for telling the compiler just how those types are to be used.

Visual C++ provides many of the building blocks for mixing native and managed types but in some cases you need to write a little code to help it along. Fortunately C++/CLI is very capable. Let’s consider a few different scenarios.

Embed Simple Managed Type in Native Type

Since the CLR needs to keep track of every single instance of a managed type in a process, storing some kind of reference/pointer/handle to a managed object in a native type is not directly supported since instances of native types can be allocated in any region of memory and cast to all kinds of foreign data types that would be completely opaque to the CLR and its services. Instead you need to register such occurrences with the CLR so that it is aware of these “native” references to managed types. This is achieved with the use of the GCHandle type. Internally GCHandle manages a static table of (native) pointers that are used to lookup the objects in the managed heap. Of course using GCHandle directly from C++ can be quite tedious. It’s a CLS compliant value type which means native pointers are represented by IntPtr values. It also does not preserve static type information so static_casts are inevitable. Fortunately Visual C++ ships with the gcroot native template class that provides a strongly-typed interface over the GCHandle type.

#include <vcclr.h>
 
ref struct ManagedType
{
    void HelloDotNet()
    {
        Console::WriteLine("Hello .NET");
    }
};
 
struct NativeType
{
    ManagedType m1;          // Error!
   
    ManagedType^ m2;         // Error!
   
    gcroot<ManagedType^> m3; // OK
};
 
void main()
{
    NativeType native;
    native.m3 = gcnew ManagedType;
 
    native.m3->HelloDotNet();
}

As you can see, gcroot provides a “smart” pointer for storing handles in native types. It may be smart but it does not provide automatic cleanup of resources. Specifically, the gcroot destructor makes no attempt to dispose of the managed object’s resources.

Embed Managed Resource in Native Type

Enter the auto_gcroot class. This native template class wraps a gcroot and provides transfer-of-ownership semantics for managed objects stored in native types. If you’re looking for a point of reference, think of the auto_ptr template class from the Standard C++ Library which does the same thing for native pointers. The auto_gcroot destructor takes care of “deleting” the handle which results in the object’s IDisposable::Dispose method (if any) being called.

#include <msclr\auto_gcroot.h>
 
ref struct ManagedType
{
    void HelloDotNet()
    {
        Console::WriteLine("Hello .NET");
    }
 
    ~ManagedType()
    {
        Console::WriteLine("dtor");

        // Compiler implements Dispose pattern...
    }
};
 
struct NativeType
{
    msclr::auto_gcroot<ManagedType^> m3; // OK
};
 
void main()
{
    NativeType native;
    native.m3 = gcnew ManagedType;
 
    native.m3->HelloDotNet();
}

The NativeType destructor (provided by the compiler) will automatically call the auto_gcroot destructor which will delete the managed object resulting in its destructor being called through its compiler generated Dispose method.

Embed Native Type in Managed Type

Now let’s turn things around. Let’s say we want to store a native type as a member of a managed type. The challenge is that the only native type the CLR really supports within managed types is a native pointer. C# programmers use IntPtr but that is only because IntPtr is the CLS compliant way of representing a native pointer and C# tries really hard to remain CLS compliant. The CLR fully supports storing native pointers without losing type information.

struct NativeType
{
};
 
ref struct ManagedType
{
    NativeType n1; // Error!

    NativeType* n2; // OK
};

That’s great except that now we have a resource management issue. Recall that C++ does not have the separation of memory and resource management evident in the CLR. The native object pointed to by the ManagedType member needs to be deleted. Here is one solution.

ref struct ManagedType
{
    NativeType* n2; // OK
 
    ~ManagedType()
    {
        if (0 != n2)
        {
            delete n2;
            n2 = 0;
        }
    }
};

Now the ManagedType has a Dispose implementation that will faithfully delete the native object. But this can become tedious and error prone very quickly. A better solution is to use some kind of “automatic” approach. Fortunately C++/CLI support by-value semantics for members so all we need is a managed auto-pointer template class. With such a class the ManagedType becomes really simple.

ref struct ManagedType
{
    AutoPtr<NativeType> n2; // OK
};

ManagedType stores a pointer to a native object and its destructor automatically deletes the object. Woohoo!

The C++ compiler really takes care of a lot of boilerplate code. If you’re not sure just how much code the compiler is taking care of for you then take a look at the compiled assembly in a disassembler.

Although Visual C++ does not provide a managed AutoPtr class, it is reasonably simple to write one. Here is a basic implementation.

template <typename T>
ref struct AutoPtr
{
    AutoPtr() : m_ptr(0)
    {
        // Do nothing
    }
    AutoPtr(T* ptr) : m_ptr(ptr)
    {
        // Do nothing
    }
    AutoPtr(AutoPtr<T>% right) : m_ptr(right.Release())
    {
        // Do nothing
    }
    ~AutoPtr()
    {
        if (0 != m_ptr)
        {
            delete m_ptr;
            m_ptr = 0;
        }
    }
    T& operator*()
    {
        return *m_ptr;
    }
    T* operator->()
    {
        return m_ptr;
    }
    T* Get()
    {
        return m_ptr;
    }
    T* Release()
    {
        T* released = m_ptr;
        m_ptr = 0;
        return released;
    }
    void Reset()
    {
        Reset(0);
    }
    void Reset(T* ptr)
    {
        if (0 != m_ptr)
        {
            delete m_ptr;
        }
        m_ptr = ptr;
    }
private:
    T* m_ptr;
};

In a future post I may provide a few realistic examples of mixing native and managed code, but I hope this introduction has given you a few ideas on how to mix native and managed code and types effectively in C++.


© 2005 Kenny Kerr

 

Posted by KennyKerr with 25 comment(s)
Filed under: ,

I'm an MVP!

Microsoft MVP Please welcome the newest member of the Microsoft House of Representatives.

:)

I just got the word from Rafael Munoz that I have received the Microsoft MVP Award. It’s been a really fun year writing articles, blogging and just generally getting more involved in the community. Thanks to Brian Johnson for nominating me and Rafael, my MVP Lead at Microsoft, for driving it from there.

I am honored to be recognized among such outstanding individuals like Keith Brown, Scott Hanselman, and the many other MVPs that serve the Windows developer community.


© 2005 Kenny Kerr

Posted by KennyKerr with 9 comment(s)
More Posts