Re: is there any good pratice f or error handling in Win32 & COM
development?
I'm exceptions-guy, so I disagree with Scott and David here ;-)
Use exceptions, that's all there is. Take care not to abuse them,
that's all (rule of thumb: look for stuff that can "fail" as a matter
of fact - that's where you should avoid exceptions. E.g. operations of
type "FindX" should be able to fail without exceptions).
Here's why you want exceptions:
There's __no__ C++ without exceptions. Compiler COM support classes
throw exceptions, ATL classes throw exceptions, standard C++ library
throws exceptions, MFC throws exceptions, simplest things in C++ like
s=string1+string2 are either not possible or are poorly defined
without exceptions...
In practice, there's a way to "avoid" exceptions with C++, and that is
to say: there will be no exceptions in my code except for out-of
memory conditions, and for that, I'll just crash. Here's how that
approach works:
0. you crash on failed "operator new" (and malloc) (you can rig these
to do it)
1. you either don't use standard library, or you consider any errors
thrown by it as bugs (e.g. you get, I think range_error, if you index
a std::vector with bad index; that's easy to consider a bug anyhow,
and so program should just crash there.)
2. if you use any external libraries that throw, you wrap all calls to
them in an appropriate try-catch.
3. you don't use boost, you don't use compiler COM support, you don't
use MFC.
That, to me, is a horrible way to code. Don't do that. Don't live in
la-la-la-la land of exceptions-free C++.
Rather, learn RAII, learn exception safety guarantees, learn
ScopeGuard, learn non-throwing swap idiom. Or, as they say, when in
Rome, do as Romans do. ATL is a C++ library, end of.
I disagree with David's implication that somehow try-catch is messy.
That implies that incessant if(FAILED(Whatever)) isn't. Ideally, try-
catch statements in C++ code are __very rare__ (or else, it's done
wrong ;-). In COM code, that amounts to STDMETHODIMPL calls (COM
boundaries). And there, ideally, you can get to canonical form of
style:
STDMETHODIMPL CMyObjImpl::MyMethod(params)
{
try
{
// Code, code, code
}
catch(const your_base_exception_class& e) { return ConvertToCOMError
(e); }
// NB: you make sure that ConvertToCOMError is a nothrow function.
}
You can of course, leave try/catch out for simple STDMETHODIMPL stuff
(e.g. trivial primitive type setters/getters, stuff like that).
HTH,
Goran.