IntroductionI recently read Vadim Kokielov's article on Windows' SEH, but I think that there were some unfair, and perhaps hasty, conclusions reached in the comparison of Windows' SEH with C++ EH. My article is intended to be a rebuttal and is provided merely for additional insight into the topic of C++ EH. It is not intended to be completely unbiased. If anyone can correct me on these arguments and suggestions (particularly Vadim) I would appreciate it and post the conclusions as updates here, or perhaps as a part 2 of this article, if the GDnet staff is willing to format it (Ed.- we are). Please do not post a reply intended for me on the GDNet message boards. Any email I get containing any of the following: violent replies, wild assumptions, and any arguments related to C vs. C++ or OOP vs. Structured Programming will be deallocated immediately :) and no credit will be given to the author of such crap in the event that he/she manages to provide useful information. Onward to the rebuttal. :) Termination HandlersIn comparison with C++ exception-handling, termination handlers really only matter for resources that will not be deallocated by destructors (i.e., temporary resources dynamically allocated by non-C++ code from inside a function, or from inside a constructor). In all other instances, a properly-written destructor will be able to clean it up. For such special instances, one can easily write a class template that will take advantage of the destructor calls made when local variables go out of scope. It only has to be written once (per programmer lifetime :), plus a simple deallocator (in most cases, a single function call). I would remind you that although the deallocator has to be written (once per type, not per instance) and the template class instantiated in C++ EH, in SEH you would have to write the deallocation function calls in your __finally block anyway. ExamplesThe class template need only be a slightly modified version of std::auto_ptr. For example, namespace auto { namespace deallocation { template <typename T> struct heap { void operator () (T* const pointer) { delete pointer; } }; struct handle { void operator () (HANDLE const handle) { CloseHandle(handle); } }; struct bitmap { void operator () (HBITMAP const handle) { DeleteObject(handle); } }; struct window { void operator () (HWND const handle) { DestroyWindow(handle); } }; struct file { void operator () (FILE* const handle) { _fclose(handle); } }; struct com_object { void operator () (IUnknown* const handle) { handle->Release(); } }; // etc. }; template <typename T, typename D = deallocation::heap<T> > class handle { T* pointer; D deallocate; public: handle(T* const pointer) : pointer(pointer) {} ~handle() { if( pointer ) deallocate(pointer); } // ... }; }; Then you simply use it similarly to std::auto_ptr, substituting any custom deallocators when the need arises: void myclass::myclass(const char* const filename) { auto::handle<some_big_class> bc = new some_big_class; auto::handle<FILE, auto::deallocation::file> fp = _fopen(filename, "r"); // bc and fp are automatically closed whether or not an exception is thrown } Personally, I think that std::auto_ptr should have been written to support custom deallocators. Note that a partial specialization of auto::handle should be written to include Windows' handle types and all other types that require the first template argument be a pointer type. ConclusionThis solution has the following benefits over SEH:
|
|||||||||||