This is covered by any halfway-decent C++ book, but I believe it deserves reiteration: Use the RAII idiom. I don’t think I could explain RAII any better than HackCraft does in The RAII Programming Idiom.
Let me demonstrate how to use RAII with a semi-contrived example. Here’s the pre-RAII code:
In this case, the resource wrapped is
HMODULE, the resource acquisition function is
LoadLibrary(), and the resource release function is
FreeLibrary(). Beware of resources which have multiple resource release functions, such as Win32’s
CloseHandle(); for these cases you will typically have to write multiple RAII classes. I will call the wrapper class
HModule. Here’s how its use will look:
Things to note:
- I replaced the assignment statement
HMODULE hm = LoadLibrary(_T("user32.dll"));with the construction statement
HModule hm(LoadLibrary(_T("user32.dll")));. On newer compilers this may not be necessary.
HModuleneeds to handle the case where
LoadLibrary()fails—it must not call
FreeLibrary()on an invalid
HMODULE. Be careful of types such as
HANDLEas it uses both
INVALID_HANDLE_VALUEto denote invalid values.
HModuleshould be transparently convertible to a
HMODULE. This implies either inheriting from
HMODULEor, preferably, providing a conversion operator to
HMODULE. (Some resource wrapping classes, like STL’s
std::basic_string, prefer a method rather than a conversion operator (
c_str()in this case), probably to minimize unexpected, implicit conversions. The choice is up to you.)
- If a user calls
FreeLibrary(hm);that will result in a double-free, a potentially dangerous bug. I don’t think there’s a whole lot that can be done about this besides saying “Don’t do that!”
- We need to worry assignment and the copy constructor: the default implementations will lead to double-free bugs. A few solutions are: disabling the operators, but this makes the class less useful than it could be; turning assignment/copy construction into transfer of ownership like STL’s
std::auto_ptr, but this causes some unexpected semantics; or using reference counting like Boost’s
shared_ptr, but this adds often-unneeded complexity and, by itself, introduces the problem of circular references. For simplicity, I will simply choose to disable assignment and the copy constructor.
Given these observations, here’s my version of
Obviously, there’s a lot more that can be done to
HModule, such as supporting release of ownership, reassignment, etc. However, by using RAII classes like
HModule exclusively, you will immediately reap the gains of less thought about resource management, fewer bugs, and you will be one step closer towards exception safety.
BTW, if you don’t want to go to the trouble of writing RAII classes, there’s also ScopeGuard.