Click here to Skip to main content
Click here to Skip to main content

Automatic release of Win32 objects

By , 9 Nov 2006
 

Introduction

I like to use auto_ptr whenever is possible. It handles a lot of work for me, and saves a lot of debugging time. But couldn't I use the mechanism for other things than pointers? Of course: Win32 objects.

Background

There are some cases where I have to write a large initialization function that creates some handles. It is expected that I check the error code and, if something goes wrong somewhere, I close the created handles and exit the function, just like in the example below.

BOOL Start()
{
    HANDLE hEvt = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (NULL == hEvt)
    {
        printf("Failed to create stop event\n");
        return FALSE;
    }

    HKEY hRegKey;
    if (RegCreateKey(HKEY_LOCAL_MACHINE, "File", &hkey)) 
    {
        printf("Failed to create registry key");

        CloseHandle(hEvt);
        return FALSE;
    }

    HANDLE hFile = CreateFile("registryfile.txt", ...);
    if (NULL == hFile)
    {
        printf("Failed to create file\n");

        RegCloseKey(hRegKey);
        CloseHandle(hEvt);
        return FALSE;
    }

    // .. read something from file

    CloseHandle(hFile);
    RegCloseKey(m_resVal.regKey);
    CloseHandle(hEvt);
    return TRUE;
}

I really don't like this style, because there are a lot of ways this can go wrong:

  • I forget to add code for closing handles.
  • Later in the development stage, I forget to add code for closing handles.
  • Other programmers change my function and doesn't add code to close the handles.
  • An unhandled exception is thrown.
Therefore, I developed a class that can dispose resources in the destructor, just like auto_ptr works. For the moment, there are only a few objects supported, but I intend to expand the class whenever I feel the need to add a new Win32 object.

Using the code

It's as simple as declaring an AutoRes variable whose constructor receives the handle you want to forget about. This is how the function would look like now:

BOOL Start()
{
    HANDLE hEvt = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (NULL == hEvt)
    {
        printf("Failed to create stop event\n");
        return FALSE;
    }
    AutoRes evtRes(hEvt);

    HKEY hRegKey;
    if (RegCreateKey(HKEY_LOCAL_MACHINE, "File", &hkey)) 
    {
        printf("Failed to create registry key");

        return FALSE;
    }
    AutoRes regRes(hRegKey);

    HANDLE hFile = CreateFile("registryfile.txt", ...);
    if (NULL == hFile)
    {
        printf("Failed to create file\n");

        return FALSE;
    }
    AutoRes fileRes(hFile);

    // .. read something from file

    return true;
    // automatic resource release
}

Points of Interest

The class is designed to work as fast as possible and be very small, and some flexibility was sacrificed in the name of speed and simplicity.

Since an instance can only hold a type of handle at a time, a union is used to hold the resource that is to be deleted. An instance can be initialized with specialized constructors, as well as with some specialized functions.

To add a new Win32 object, you'll have to:

  1. If the object is of type HANDLE and is closed with CloseHandle(), use the existing constructor.
  2. If the object is of type HANDLE and is not closed with CloseHandle(), add a new entry in the ResType enumeration, add to the specialized constructor that receives a HANDLE and an enum, then add to the Release() function code for releasing the HANDLE.
  3. If it's not a HANDLE object, add a new entry in the ResType enum and in the ResVal union, add a specialized constructor, and edit the Release() function.
  4. That's all.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Andrei Muraru
Web Developer
Romania Romania
Member
After I finished the university, I worked for two years in gaming industry, as a programmer in DirectX environment.
After that, I switched to computer security, which is a fascinating domain, where a lot of stuffs can be learn and experimented.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 2memberAlexandre GRANVAUD30 Dec '08 - 21:08 
Generalexceptionsmemberchdb30 Oct '07 - 7:16 
Generalauto_pointermemberchdb30 Oct '07 - 6:58 
GeneralAnother approachmemberj337y d0nut15 Nov '06 - 10:56 
GeneralSome remarksmemberRoland Pibinger9 Nov '06 - 9:02 
GeneralRe: Some remarksmemberAndrei Muraru9 Nov '06 - 10:07 
If you look at the code, you'll see some function for initialization that can be used instead of constructors, as well as a function Detach(), that will release the automatic deletion of the handle. Returning the handle it's a bit trickier, since you must return different types, so you'll have different functions, wich will lose from the class transparency.
 
I know much about Alexandrescu's work, and I think it's good to have this class at your disposal to quickly jump into developing real code.
QuestionCode?memberShawn Poulson9 Nov '06 - 4:25 
AnswerRe: Code?memberandrei50089 Nov '06 - 4:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 9 Nov 2006
Article Copyright 2006 by Andrei Muraru
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid