new(nothrow not even from constructor)

V

Virchanza

I've been looking through the Dinkumware reference manual and I
can't find a form of "new" that doesn't throw any exceptions at all.

I'm currently writing a program that uses the "new" operator to do
stuff like create thread objects and window objects. If a thread
object or window object can't be created, my program displays a
message box, something like "Creation of the Help dialog box failed".
Ideally it would be:

Thread *const p = new(std::nothrow) Thread(my_entry_function,
JOINABLE);

if (!p)
{
wxMessageBox("Can't create thread");
return;
}


The problem with this however, is that don't want any exceptions at
all to be thrown by the "new" operator. For instance, the following
"Hello World" program doesn't work:

#include <new>
#include <iostream>

class MyClass {
public:

MyClass()
{
throw 5;
}
};

int main()
{
MyClass *p = new(std::nothrow) MyClass();

std::cout << "Hello World!\n";
}

The "nothrow" only stops "new" from throwing a "bad_alloc" if the
memory allocation fails -- it doesn't suppress exceptions thrown from
the constructor of the object. (Or at least that's the GNU C++
behaviour).

Is the following my only option?

int main()
{
MyClass *p;

try { p = new MyClass(); } catch(...) { p = 0; }

std::cout << "Hello World!\n";
}
 
B

Bo Persson

Virchanza said:
I've been looking through the Dinkumware reference manual and I
can't find a form of "new" that doesn't throw any exceptions at all.

I'm currently writing a program that uses the "new" operator to
do stuff like create thread objects and window objects. If a thread
object or window object can't be created, my program displays a
message box, something like "Creation of the Help dialog box
failed". Ideally it would be:

Thread *const p = new(std::nothrow) Thread(my_entry_function,
JOINABLE);

if (!p)
{
wxMessageBox("Can't create thread");
return;
}


The problem with this however, is that don't want any exceptions at
all to be thrown by the "new" operator. For instance, the following
"Hello World" program doesn't work:

#include <new>
#include <iostream>

class MyClass {
public:

MyClass()
{
throw 5;
}
};

int main()
{
MyClass *p = new(std::nothrow) MyClass();

std::cout << "Hello World!\n";
}

The "nothrow" only stops "new" from throwing a "bad_alloc" if the
memory allocation fails -- it doesn't suppress exceptions thrown
from the constructor of the object. (Or at least that's the GNU C++
behaviour).

It DOES stop "new" from throwing, it just doesn't stop "MyClass()"
from throwing. .-)

What about

MyClass *p = new(std::nothrow) MyClass(std::nothrow);

??
Is the following my only option?

int main()
{
MyClass *p;

try { p = new MyClass(); } catch(...) { p = 0; }

std::cout << "Hello World!\n";
}

Pretty much, yes.

Another thing to consider is that if "new" or "MyClass" throws because
of lack of resources, what are the odds that wxMessageBox will work at
that point? Isn't that trying to create a window telling you that
creating a window just failed?!


Bo Persson
 
V

Virchanza

Another thing to consider is that if "new" or "MyClass" throws because
of lack of resources, what are the odds that wxMessageBox will work at
that point? Isn't that trying to create a window telling you that
creating a window just failed?!


Some of the objects I create are quite complicated in their
construction. For instance, if I create a thread object for sniffing a
network interface, it could fail for all sorts of reasons... lack of
memory, inability to open the network interface. If creation of the
object fails, I want to handle it gracefully without killing my
program.

Here's what I've resorted to doing:

#define NEW_NULL_FAIL(p,x) \
do \
{ \
try \
{ \
p = new(std::nothrow) x; \
} \
catch (...) \
{ \
p = 0; \
} \
} while (0)


So now my code is something like:

Thread *p;

NEW_NULL_FAIL(p, Thread(entry_func,JOINABLE));

if (!p)
{
wxMessageBox(...
return;
}

ContinueOn();
 
F

Fred Zwarts

Virchanza said:
Some of the objects I create are quite complicated in their
construction. For instance, if I create a thread object for sniffing a
network interface, it could fail for all sorts of reasons... lack of
memory, inability to open the network interface. If creation of the
object fails, I want to handle it gracefully without killing my
program.

Here's what I've resorted to doing:

#define NEW_NULL_FAIL(p,x) \
do \
{ \
try \
{ \
p = new(std::nothrow) x; \
} \
catch (...) \
{ \
p = 0; \
} \
} while (0)


So now my code is something like:

Thread *p;

NEW_NULL_FAIL(p, Thread(entry_func,JOINABLE));

if (!p)
{
wxMessageBox(...
return;
}

ContinueOn();

Why are you using nothrow?
What is against using exceptions as the were meant?

Thread *p;
try {
p = new Thread(entry_func,JOINABLE);
} catch (...) {
wxMessageBox(...
return
}

ContinueOn();
 
V

Virchanza

Why are you using nothrow?

You're right, it's not necessary.
What is against using exceptions as the were meant?

Thread *p;
try {
   p = new Thread(entry_func,JOINABLE);} catch (...) {

   wxMessageBox(...
   return

}

ContinueOn();


I've been using null pointers for so long, I just prefer them. Plus I
find the "try catch" notation to be a bit long-winded.
 
R

Ruslan Mullakhmetov

You're right, it's not necessary.



I've been using null pointers for so long, I just prefer them. Plus I
find the "try catch" notation to be a bit long-winded.

you could probably use operator new overloading, but i'm not sure. never
overloaded one.
 
R

red floyd

you could probably use operator new overloading, but i'm not sure. never
overloaded one.


Or you could do this:


template<typename T>
T* new_thread(Func_type f, int state)
{
T* ret = NULL;
try {
ret = new Thread(f, state);
}
catch (...) {
// do something, or not
}

return ret;

}
 
G

Goran

I've been using null pointers for so long, I just prefer them. Plus I
find the "try catch" notation to be a bit long-winded.

try/catch is longer than an "if", but if your code has a lot of try/
catch-ing, you're doing it wrong. As opposed to ifs of error-return,
you should have about an order of magnitude less try/catch-es with
exceptions. Indeed, your attempt to catch failure in object creation
the way you have shown, is IMO wrong.

There's no modern C++ without exceptions (at least, there's very
little of it). Everything throws. new throws, string1+string2 throws,
push_back throws (because new throws, and you can't use non-throwing
new because of that)...

I seriously suggest that you change your preference, because if you
don't, you will constantly fight an uphill battle while working.

Goran.
 
R

Ruslan Mullakhmetov

Or you could do this:


template<typename T>
T* new_thread(Func_type f, int state)
{
T* ret = NULL;
try {
ret = new Thread(f, state);
}
catch (...) {
// do something, or not
}

return ret;

}

Or I think it makes sense to get new_thread as static function-member of
Thread class say Thread::create. I'd prefer this, cause it number of
reduces global scoped free functions.
 
R

red floyd

Or I think it makes sense to get new_thread as static function-member of
Thread class say Thread::create. I'd prefer this, cause it number of
reduces global scoped free functions.


Yeah, I kind of switched gears mid-stream -- I started with a generic
template to deal with any type of create and then halfway through
switched to "Thread" specific -- mainly because I couldn't remember
the syntax for variadic templates.

My intent was to provide a generic "new" for OP that catches all
exceptions, including those thrown by the constructor.
 
R

Ruslan Mullakhmetov

Yeah, I kind of switched gears mid-stream -- I started with a generic
template to deal with any type of create and then halfway through
switched to "Thread" specific -- mainly because I couldn't remember
the syntax for variadic templates.

My intent was to provide a generic "new" for OP that catches all
exceptions, including those thrown by the constructor.

I'm sorry, didn't take into account that it was templatized. I think,
there is no need for variadic templates to make it general new. SFINAE
allow, if i'm not mistaken to make variable number of parameters passed
to constructor through this generalized exception-free new.

template<typename T>
T* my_new()
{
T* ret = NULL;
try {
ret = new T;
}
catch (...) {
// do something, or not
}

return ret;
}

template<typename T, typename P1>
T* my_new(P1 p1)
{
T* ret = NULL;
try {
ret = new T(p1);
}
catch (...) {
// do something, or not
}

return ret;
}

template<typename T, typename P1, typename P2>
T* my_new(P1 p1, P2 p2)
{
T* ret = NULL;
try {
ret = new T(p1, p2);
}
catch (...) {
// do something, or not
}

return ret;
}

//...
 
R

red floyd

I'm sorry, didn't take into account that it was templatized. I think,
there is no need for variadic templates to make it general new. SFINAE
allow, if i'm not mistaken to make variable number of parameters passed
to constructor through this generalized exception-free new.

template<typename T>
T* my_new()
{
        T* ret = NULL;
        try {
                ret = new T;
        }
        catch (...) {
                // do something, or not
        }

        return ret;

}

template<typename T, typename P1>
T* my_new(P1 p1)
{
        T* ret = NULL;
        try {
                ret = new T(p1);
        }
        catch (...) {
                // do something, or not
        }

        return ret;

}

template<typename T, typename P1, typename P2>
T* my_new(P1 p1, P2 p2)
{
        T* ret = NULL;
        try {
                ret = new T(p1, p2);
        }
        catch (...) {
                // do something, or not
        }

        return ret;

}

//...

Yeah, that's what I was thinking...
 

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

Staff online

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top