Exceptions & Constructors

J

jalqadir

The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Thanks folks!
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Sure, add a flag to the class that tells if the object was constructed
correctly:

class Foo {
int* ptrarr[16];
public:
bool correct;
Foo() correct(true) {
try {
for (size_t i = 0; i < 16; ++i)
ptrarr = new int();
} catch(bad_alloc&) {
correct = false;
}
}
};

int main() {
Foo f;
if (f.correct == false) {
// Opps, failed to allocate
}
}
 
J

Jim Langston

The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Well, what do you want your code to do on failure?

Consider:

class Foo
{
// ...
};

int main()
{
Foo Bar;
}

What do you want to happen if Bar can not be instantized because of bad
allocation inside of Foo's constructor? And how do you want to check if it
was successful?

Some things I can think of off the top of my head.

1. Have Foo contain a private bool variable stating if all pointers have
been instantized correctly with newed instances. Alternative to this, is to
check any of the pointers itself for a NULL value which you would set in the
constructor if initializaiton of the variables failed. Foo could have a
method returning if it was initalized or not. Foo could have it's internal
methods checking initialzation.

2. Have Foo created only by a factory (I.E returning a pointer). If Foo can
not be instantized, the factory returns NULL which mainline can check.

3. Do nothing and have new's throw propogate up to mainline

I could think of a few other methods depending on what you would want done.
It is not a good thing to have an instance floating around that was not
properly instantized. How are you going to provent this if you don't allow
new's throw to propogate? How do you WANT to prevent it?
 
G

Gianni Mariani

Erik said:
The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Sure, add a flag to the class that tells if the object was constructed
correctly:

class Foo {
int* ptrarr[16];
public:
bool correct;
Foo() correct(true) {
try {
for (size_t i = 0; i < 16; ++i)
ptrarr = new int();
} catch(bad_alloc&) {
correct = false;
}
}
};

int main() {
Foo f;
if (f.correct == false) {
// Opps, failed to allocate
}
}


That code leaks if it fails. Should you not have to delete all of them
or at lease assign a null pointer ?
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Erik said:
The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Sure, add a flag to the class that tells if the object was constructed
correctly:

class Foo {
int* ptrarr[16];
public:
bool correct;
Foo() correct(true) {
try {
for (size_t i = 0; i < 16; ++i)
ptrarr = new int();
} catch(bad_alloc&) {
correct = false;
}
}
};

int main() {
Foo f;
if (f.correct == false) {
// Opps, failed to allocate
}
}


That code leaks if it fails. Should you not have to delete all of them
or at lease assign a null pointer ?



Actually it does not even compile, I forgot the : in the initialisation
list and have not included the headers for bad_alloc etc. It was more to
show the OP the general idea then to give him/her code that worked, as
an example I don't expect that the OP has an array of pointers but
rather a number of pointers, which should then be initialised to null in
the initialisation list before allocating memory with new. Or perhaps
using some kind of smart pointer.
 
R

Roy

Erik said:
On 2007-07-30 13:15, (e-mail address removed) wrote:
The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?
Sure, add a flag to the class that tells if the object was constructed
correctly:
class Foo {
int* ptrarr[16];
public:
bool correct;
Foo() correct(true) {
try {
for (size_t i = 0; i < 16; ++i)
ptrarr = new int();
} catch(bad_alloc&) {
correct = false;
}
}
};
int main() {
Foo f;
if (f.correct == false) {
// Opps, failed to allocate
}
}

That code leaks if it fails. Should you not have to delete all of them
or at lease assign a null pointer ?

Actually it does not even compile, I forgot the : in the initialisation
list and have not included the headers for bad_alloc etc. It was more to
show the OP the general idea then to give him/her code that worked, as
an example I don't expect that the OP has an array of pointers but
rather a number of pointers, which should then be initialised to null in
the initialisation list before allocating memory with new. Or perhaps
using some kind of smart pointer.


the lost : in the initialization list had me confused ! :-( , thanks
for clearing this up !
What you have suggested is an elegant way of handling an exception ,
what else is bool used for ?
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Erik Wikström wrote:
On 2007-07-30 13:15, (e-mail address removed) wrote:
The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?
Sure, add a flag to the class that tells if the object was constructed
correctly:
class Foo {
int* ptrarr[16];
public:
bool correct;
Foo() correct(true) {
try {
for (size_t i = 0; i < 16; ++i)
ptrarr = new int();
} catch(bad_alloc&) {
correct = false;
}
}
};

int main() {
Foo f;
if (f.correct == false) {
// Opps, failed to allocate
}
}
That code leaks if it fails. Should you not have to delete all of them
or at lease assign a null pointer ?

Actually it does not even compile, I forgot the : in the initialisation
list and have not included the headers for bad_alloc etc. It was more to
show the OP the general idea then to give him/her code that worked, as
an example I don't expect that the OP has an array of pointers but
rather a number of pointers, which should then be initialised to null in
the initialisation list before allocating memory with new. Or perhaps
using some kind of smart pointer.


the lost : in the initialization list had me confused ! :-( , thanks
for clearing this up !
What you have suggested is an elegant way of handling an exception ,
what else is bool used for ?


For storing anything that can only have two different values. It is not
uncommon to get into a situation where you want to check something, and
the answer can then either be true or false, such as is a container
empty? Does the container contain a specific element? In all those cases
bool is a suitable return type.

It is also used to check conditions in loops and control-statements, the
==, !=, <, >, <=, and >= operators (along with some I probably forgot)
all return a value of type bool (or something convertible to bool). As
an example a while-loop loops as long as the condition is true, so an
infinite loop can be written like this:

while (true)
{
// ...
}
 
T

tragomaskhalos

The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

It's worth considering the role of the subordinate object ...
I know you said you wanted to avoid exceptions emerging from your
MyClass ctor, but if the subordinate objects are really an
indivisible part of the MyClass object, ie a MyClass doesn't make
any sense without them and isn't usable unless they are there,
then letting the exception propagate out of the ctor makes sense
and can make your code a lot cleaner. Eg:

MyClass x;
x.good_I_must_have_a_fully_consed_MyClass_now();

It's worth bearing in mind that many deem propagating exceptions from
ctors to be the correct way of handling this sort of situation, and
view setting a 'constructed ok' flag as a hack best avoided.

Alternatively if the MyClass instance is usable without a subordinate,
then you can absorb the bad_alloc in the MyClass ctor and flag the
absence of the subordinate object with a null pointer:

MyClass x;
if (x.ptr_to_nice_to_have != 0) // nb should encapsulate properly
x.some_method_using_nice_to_have();


Cheers.
 
T

tragomaskhalos

Alternatively if the MyClass instance is usable without a subordinate,
then you can absorb the bad_alloc in the MyClass ctor and flag the
absence of the subordinate object with a null pointer:
Er, or indeed use a nothrow new and get a null ptr without having to
worry
about bad_alloc at all.

But to amplify my previous point, exceptions are your friends: too
often
people want to catch exceptions as soon as they are thrown and
convert
them into flags or error codes, which obviates the whole purpose of
them,
which is to free a program's logic from endlessly having to check
niggling
little will-only-happen-in-extremely-rare-and-bad-situation failures.
 
A

Alf P. Steinbach

* Erik Wikström:
The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Sure, add a flag to the class that tells if the object was constructed
correctly:

class Foo {
int* ptrarr[16];
public:
bool correct;
Foo() correct(true) {
try {
for (size_t i = 0; i < 16; ++i)
ptrarr = new int();
} catch(bad_alloc&) {
correct = false;
}
}
};

int main() {
Foo f;
if (f.correct == false) {
// Opps, failed to allocate
}
}


Ouch, this is /very/ bad.

There's only one reasonable way to deal with memory depletion on a
modern system (until we get better operating systems), and that's to
install a terminating new handler.

Otherwise the program will continue to trash and will continue to fail,
and it's virtually guaranteed that some part of the code isn't able to
handle that.

And there's only one reasonable way to deal with construction failure,
and that is to throw an exception.

Otherwise you have zombie objects, requiring checking all over the place
and generally creating bugs & complexity, and that's what you have here.
You might want to consult Bjarne's article on exception safety in the
standard library. Available on net and as appendix to TCPPPL 3rd ed.

The memory leak in the code above is, in comparision, barely worth
mentioning, bad yes, but not a catastrophe like each of the two earlier
points.

Cheers,

- Alf
 
X

Xavier Serrand

The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Thanks folks!

If you mind, a static function could be used... returning NULL in case of
failure...

Just like that :

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;
}
}

But remember what Alf P. Steinbach said !!

Xavier
 
T

tragomaskhalos

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.
 
B

BobR

Erik Wikström wrote in message...
The constructor in MyClass instantiates many objects pointers through
'new', I would like to implement a way to make sure that the object
has been allocated in memory by catch(ing) the bad_alloc exception
error, but this means that I have to throw this error back from
MyClass constructor, how can I avoid this?

Sure, add a flag to the class that tells if the object was constructed
correctly:

class Foo {
int* ptrarr[16];
public:
bool correct;
Foo() correct(true) {
try {
for (size_t i = 0; i < 16; ++i) ptrarr = new int();
} catch(bad_alloc&){ correct = false; }
}
};

int main() {
Foo f;
if (f.correct == false) {
// Opps, failed to allocate
}
}


Re-worked for 'function-level try block' (just for an idea(OP)):

#include <stdexcept> // #include <exception>
#include said:
class Foo{
int *ptrarr[16];
public:
bool correct;

Foo() try : correct( true ) {

for (size_t i = 0; i < 16; ++i) ptrarr = new int();
} catch( std::bad_alloc&){
correct = false;

// delete what you new.
// throw;
} // catch
}; // class Foo


// or, the extreme: (not borland6)
#include <iostream> // #include <ostream>
#include <stdexcept>
#include <new> // bad_alloc

int main() try {
Foo f; // un-comment "throw;" in Foo's "catch()"
// throw "failure in main()"; // to test
} // main() end
catch( char const *msg) {
std::cout << msg << std::endl;
return 1;
}
catch( std::bad_alloc&){
std::cout <<" Opps, failed to allocate!"<<std::endl;
// throw;
return 1;
} // catch
catch( ... ){
std::cout <<" Unknown failure!"<<std::endl;
return 1;
} // catch


Erik, I started to toss out this post[1], but, seeing other posts, it may
help somebody.

[1] - I only wanted to inform you I found your lost colon. :-}
Was that an "colon-oscopy"(sp?)?
[ corrections, comments welcome. ]
 
X

Xavier Serrand

tragomaskhalos said:
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.
object could hav been constructed and bad_alloc raised ... after if one or
more members are pointers
For exemple :


class Something {


....
char * m_s[nbr]; // allocated by one of the constructors
....

Something ()
{...}
Something (int sz)
{allocation of m_s...}

}
 
K

Kai-Uwe Bux

Xavier said:
object could hav been constructed and bad_alloc raised ... after if one or
more members are pointers
[snip]

No.

If during evaluation of the expression

new SomeType ( some args )

memory allocation is successful but the constructor call throws (whatever it
may throw) the call to new will not return, the memory will be deallocated
and not leak, and there will not be possible way to do manual clean up
afterwards. For example, in the code above, if

pp = new File<T>( sz )

throws from the call to File<T>, the variable pp will not point to anything
meaningful. In particular, pp->~File<T>() is undefined behavior.


The upshot is: you have to write the constructor for any class in such a way
that it does not leak when subobjects and members cannot be successfully
constructed. Outside the constructor, there is no way to undo the harm that
has been done. In the above example, if File<T>() could fail, it better
fail gracefully (without resource leak) because your proposed trick to
repair things from the outside is bound to fail.

Hint: within constructors, use std::auto_ptr for allocation of multiple
pointer members.



Best

Kai-Uwe Bux
 
J

James Kanze

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.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,811
Messages
2,569,693
Members
45,477
Latest member
IsidroSeli

Latest Threads

Top