
G'day all.
Quoting Sven Panne
Granted, C++'s (copy) constructors, destructors and assignment operators make some things relatively easy compared to C, but the complexity of handling exceptions *correctly* makes things worse again: There is a famous article (I can't remember the title or the author) where a well-known C++ grandmaster explains a stack class, but another later article by someone else describes the numerous bugs in that class when exceptions are taken into account.
Far be it from me to defend C++, but this problem is far better understood today than when that GoTW article (circa 1996, from memory) was written. C++ defines two levels of exception safety: the "weak" guarantee, which merely means that there are no space leaks. This is actually quite an easy thing to guarantee. The other is the "strong" guarantee, which effectively means transaction semantics: when an exception is thrown, either the operation happened fully or it didn't at all. For operations which do not have side-effects (e.g. C++ when only manipulating local state, or Haskell when not in a stateful monad), transaction semantics are actually not that hard to do. Haskell run-time systems, for example, do it automatically, by only performing the "cell update" operation when a reduction step is complete and no further exceptions can be raised. Current C++ thinking is to do precisely the same, only manually. Prepare everything, then "update" at the end, just like a two-phase commit. If the "update" operation cannot possibly raise an exception, and everything else is weakly exception-safe, then the operation is strongly exception-safe by default. In the presence of side-effecty operations, such as I/O, neither C++ nor Haskell can provide transaction semantics without extra work from the programmer. If your disk fills up half-way through your write operation, for example, neither a C++ nor a Haskell implementation will automatically roll back the operation. If that's what you need, it's up to you to do it. Neither C++ nor Haskell programmers usually consider transaction semantics on I/O operations to be worth it, so C++ (and Haskell) programmers usually only provide weak exception safety. The point of this is that strongly exception-safe C++ is, for the most part, actually no harder in principle than memory-leak-safe C++. This wasn't generally realised in 1996, though. Cheers, Andrew Bromage