Consider the (chopped-down) definition of the basic_reg_value class:
template < . . . > class basic_reg_value { . . . private: 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.
2 comments:
Isn't the solution a little fragile though? Don't you have a more tradtional Handle class that has proper RAII semantics?
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.
Post a Comment