Re: Exceptions & Constructors
On Jul 30, 11:10 pm, tragomaskhalos <dave.du.verg...@logicacmg.com>
wrote:
On 30 Jul, 19:50, "Xavier Serrand" <xxxxxx.xxxx...@xxx.fr> wrote:
template <typename T> static Pile<T> * createPile(int sz)
{
Pile<T> * pp;
try
{
pp = new Pile<T>(sz);
return pp;
}
catch (std::bad_alloc&)
{
try
{
// clearing what can be cleared ...
// ...
// deleting the instance : the destructor has to be sure
// (may be hard to do...)
pp->~Pile<T>();
}
catch (std::exception& e)
{
// nothing to do
}
return NULL;
}
}
This is wrong isn't it? If bad_alloc is thrown then
the object won't have been constructed, so you don't
want to be calling the destructor on 'pp' - UB and
all that (not to mention the fact that pp is
uninitialised in this case anyway). In any case,
using new(nothrow) saves you having to mess about
with bad_alloc in the first place.
But as Alf has pointed out it's all largely academic,
if your program reaches this point you're probably
scuppered anyway, which reinforces my earlier
suggestion of keeping it simple and just letting the
exception propagate out of the ctor.
The problem is that Alf's point doesn't always apply. It
certainly doesn't apply on smaller, embedded systems, which
don't have much memory. And it may not always apply on larger,
general purpose systems: when, for example, the allocations are
due to a particularly complicated user request, it may make
sense to catch bad_alloc at a higher level, and report some sort
of error without bringing down the server. (A lot of protocols
provide for an "insufficient resources" error, for example, if
the request is too complicated.)
The real problem if you do want to recover is that you have to
ensure that all of the memory you've already allocated is freed.
The usual answer to this problem is "one pointer per class". A
class which needs a lot of pointers actually uses a lot of
smaller classes. And when bad_alloc (or any other exception)
pops up, the destructors for all of the already constructed
sub-objects are called, freeing the pointers. (Note that the
"smaller classes" can be as simple as boost::scoped_ptr or
std::auto_ptr; if the pointers are in a standard container,
something like boost::shared_ptr may be appropriate, or wrapping
the standard container in a special class---violating the
principle of one pointer per class, but in this case, it works,
because there won't be any uninitialized pointers, ever.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34