Preventing/handling space leaks
ajb at spamcop.net
ajb at spamcop.net
Mon Dec 8 18:18:25 EST 2003
Quoting Sven Panne <Sven.Panne at aedion.de>:
> Granted, C++'s (copy) constructors, destructors and assignment operators make
> things relatively easy compared to C, but the complexity of handling
> *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
> but another later article by someone else describes the numerous bugs in that
> 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.
More information about the Haskell-Cafe