Introduction

One of the common problems with Windows object handles to solve is to prevent resource leaks. In other words, it is necessary not to forget to call the appropriate delete handle method.

To call the appropriate delete handle method explicitly "by hand" is annoying and error prone. Moreover, to call the appropriate delete handle method during an exception is impossible. Therefore, some automatic calling of the delete handle method would be very handy.

This article describes the simple universal solution of this problem using the well-known RAII (Resource Acquisition Is Initialization) technique. It introduces a scoped handle class which calls in its destructor the appropriate delete handle method.

This scoped handle class has a very similar implementation to the smart pointer scoped_ptr from the boost C++ library.

Solution

The easy solution is to introduce the scoped handle class which calls in its destructor the delete handle method.

However, the Windows API world is not so straightforward. There is no common delete methods for all handles. For example, handle returned from the CreateEvent() API method needs to be deleted by the CloseHandle() method. But handle returned from the FindFirstFile() API method needs to be deleted by the FindClose() method.

Moreover, even the invalid handle definition is not always the same. For example, handle returned from the CreateEvent() API method is invalid when it is NULL. But handle returned from the CreateFile() API method is invalid when it is INVALID_HANDLE_VALUE.

To avoid many similar scoped handle implementations, universal template solution is introduced:

Conclusion

This article shows the implementation and usage of a scoped handle class which automatically calls the delete handle method during its destruction.

This class is easy to use, and it is flexible enough for almost all possible object handles. To use this class means to avoid any possible resource leaks, and you will not have to pay any attention to this problem anymore.

I don't see the need for this class over others I use HOWEVER that doesn't mean that there's anything wrong with the implementation of the class and ANYTHING that encourages new C++ programmers to avoid manual resource management is a good thing.

Au contraire my little downvoter, I'm well aware of how I can use unique_ptr, shared_ptr and ScopeGuard to handle windows handles. Unfortunately I don't do kernel mode programming but the examples used in the article were all user mode so I don't think I'm going to loose much sleep over this.

Consider the following (I'm using VC++2008 without SP1 installed as that's the IDE I've got open...)

typedef std::tr1::shared_ptr<void> managed_handle;

That definition will give you everything the article describes. So I can write things like:

managed_handle h( CreateMutex( 0, FALSE, 0 ), CloseHandle );

and I get a handle to the user mode image of a kernel object that will be cleaned up when the object is deleted. I can also use it as:

Ash, consider that shared_ptr is costly in term of allocation and memory (it is a two pointers holding, one of which points to a struct holding a pointer, two counters and a function pointer). May be too much for just a handle.

Also, the proposed class is completely static, while your construction-based definitions are runtime.

In the most of the cases they are equivalently functional, but sometime one may be preferable to the other.
Especially with "old compilers"

As I said, I was just using shared_ptr as that was all I had installed on the machine I replied on. How about Alexandrescu and Martigan's ScopeGuard? It's been around 10 years:

ScopeGuard managed_handle( MakeScopeGuard( h, CloseHandle) );

It's as efficient as the author's code and has the advantage of being pretty well known.

I still don't get what the author's class gives me that others don't. Don't get me wrong it's a neat idea but this sort of thing has been well known in the C++ community for 10 years and I'm going to take convincing this is better.

Cheers,

Ash

PS: Forgot to say thanks for a reasoned reply compared to the post I answered

I think ScopedGuard should be equivalent. However, the scoped handle solves the problem with different invalid handle values. So, you can use expressions like if (!File) without paying any attention which value means invalid handle in this case. So, it is less error prone and more convenient to use. So sometimes one may prefer this solution.

The idea is so old as C++ language is, so this is not the presentation of new idea, this is a presentation of handy solution for specific objects (Windows object handles).

You still have to store the CloseHandle function pointer for later use, hence, it is runtime. (And the function pointer can be even a pointer to a polymorphic object, if you want the close policy to be whatever function or functor)

About efficiency, ScopeGuard is surely more efficient then a shared_ptr, where no share is required, and may be even more efficient that the author proposal (that requires to code things around, that take their space and time).
But it is another thing.

Note that ScopeGuard is like strcpy: if you don't remember how it is named, it is faster for you to rewrite it than to search for it. That's the reason why there are at least 1000 other implementations around

That said, for the cases you are talking about, there is no much difference (you don't have milions of handles, so space is not a problem) and the code is far more clear.

It is very similar like differences between shared_ptr and scoped_ptr. Why we need scoped_ptr as well? Because it is noncopyable which is safer than shared_ptr. Because scoped_ptr is simple, every operation is as fast as for a built-in pointer and it has no more space overhead that a built-in pointer. Because scoped_ptr lets readers of your code know that you intend to use it in the current scope and transfer ownership is not needed.

Yes, you are right. The implicit type conversion operator will allow more convenient usage. But...

It will allow implicit type conversion which can be done automatically by compiler. For example, it will allow to compile constructions like "std::cout << h" which could lead to the wrong function being called. Therefore I have decided to use equivalent function to eliminate "silent" calling of implicit type conversion operator.

For more info about this topic, please refer to the Scott Meyers' book - More Effective C++, Item 5: Be wary of user-defined conversion function. The copy of this book might be available on Internet.