Monday, May 18, 2009

WinSTL Registry library mods and fixes, part 3: exception-safety

In reviewing the implementation of the WinSTL Registry Library's winstl::basic_reg_value class - as described in part 1 and part 2 of this series of posts - I've also spotted a defect in exception-safety.

Consider the (chopped-down) definition of the basic_reg_value class:
template < . . . >
class basic_reg_value
. . .
hkey_type    m_hkey; // The parent key of the value
string_type  m_name; // The name of the value
. . . // other members

The m_hkey member is obtained via winstl::reg_traits<>::reg_dup_key(). It is the basic_reg_value class itself that provides the RAII. Consequently, if any exception occur during its constructor, the release of m_hkey will not be carried out.

Since the m_name is a string class instance, its constructor can throw. Consequently, basic_reg_value is not exception safe.

Thankfully, the fix is very simple. Simply reverse the order of declaration of the two members. If m_name's constructor throws, that'll happen before the key duplication takes place. If the key duplication throws an exception, the (fully constructed) m_name's destructor will be invoked. Q.E.D.


Chris Oldwood said...

Isn't the solution a little fragile though? Don't you have a more tradtional Handle class that has proper RAII semantics?

Matt Wilson said...

Well, yes, I suppose it is. :-)

I suppose the main reason why I've not done it that way is just the principle of minimum effective change (a name I've just invented, but am happy to share credit with you ;-)

Also, in doing it - and blogging about it - in the way described, it gives readers (me included) pause to think about the exception-within-constructor rule, which is worth knowing about.

The WinSTL Registry library is up for a major rewrite in STLSoft 1.10, so maybe I'll do it the full and proper way then.