New (Std::Nothrow) VS. New Within a Try/Catch Block

New (std::nothrow) vs. New within a try/catch block

Consider what you are doing. You're allocating memory. And if for some reason memory allocation cannot work, you assert. Which is more or less exactly what will happen if you just let the std::bad_alloc propagate back to main. In a release build, where assert is a no-op, your program will crash when it tries to access the memory. So it's the same as letting the exception bubble up: halting the app.

So ask yourself a question: Do you really need to care what happens if you run out of memory? If all you're doing is asserting, then the exception method is better, because it doesn't clutter your code with random asserts. You just let the exception fall back to main.

If you do in fact have a special codepath in the event that you cannot allocate memory (that is, you can actually continue to function), exceptions may or may not be a way to go, depending on what the codepath is. If the codepath is just a switch set by having a pointer be null, then the nothrow version will be simpler. If instead, you need to do something rather different (pull from a static buffer, or delete some stuff, or whatever), then catching std::bad_alloc is quite good.

Why new std::nothrow version is not widely used

However, I hardly see this version in my experience.

You would use it (or, equivalently, catch the exception from the default version) if you can handle the failure locally; perhaps by requesting to free some other memory and then retrying, or by trying to allocate something smaller, or using an alternative algorithm that doesn't need extra memory.

Is there any reason that we prefer the default one against the nothrow one?

The general principle of exceptions: if you can't handle it locally, then there's no point in checking locally. Unlike return values, exceptions can't be ignored, so there's no possibility of ploughing on regardless and using a null pointer.

Even in a project that is not using exception?

Often, an out-of-memory condition can't be handled at all. In that case, terminating the program is probably the best response; and that is the default response to an unhandled exception. So, even if you're not using exceptions, the default new is probably the best option in most situations.

should I check return value of malloc()?

Yes: that's the only way to check whether it succeeded. If you don't, then you could end up using a null pointer, giving undefined behaviour: often a crash, but perhaps data corruption or other bizarre behaviour and long debugging sessions to (hopefully) figure out what went wrong.

Why we treat malloc() and new differently in this case?

Because malloc forces us to check the return value, while new gives us the option of less intrusive error handling.

nothrow or exception?

Since
dealing with Exceptions is heavier
compared to a simple if(t), why isn't
the normal new T() not considered less
good practice, considering we will
have to use try-catch() to check if a
simple allocation succeeded (and if we
don't, just watch the program die)??
What are the benefits (if any) of the
normal new allocation compared to
using a nothrow new? Exception's
overhead in that case is insignificant
?

The penalty for using exceptions is indeed very heavy, but (in a decently tuned implementation) the penalty is only paid when an exception is thrown - so the mainline case stays very fast, and there is unlikely to be any measurable performance between the two in your example.

The advantage of exceptions is that your code is simpler: if allocating several objects you don't have to do "allocate A; if (A) { allocate B; if (B) etc...". The cleanup and termination - in both the exception and mainline case - is best handled automatically by RAII (whereas if you're checking manually you will also have to free manually, which makes it all too easy to leak memory).

Also, Assume that an allocation fails
(eg. no memory exists in the system).
Is there anything the program can do
in that situation, or just fail
gracefully. There is no way to find
free memory on the heap, when all is
reserved, is there?

There are many things that it can do, and the best thing to do will depend on the program being written. Failing and exiting (gracefully or otherwise) is certainly one option. Another is to reserve sufficient memory in advance, so that the program can carry on with its functions (perhaps with reduced functionality or performance). It may be able to free up some of its own memory (e.g. if it maintains caches that can be rebuilt when needed). Or (in the case of a server process), the server may refuse to process the current request (or refuse to accept new connections), but stay running so that clients don't drop their connections, and things can start working again once memory returns. Or in the case of an interactive/GUI application, it might display an error to the user and carry on (allowing them to fix the memory problem and try again - or at least save their work!).

Incase an allocation fails, and an
std::bad_alloc is thrown, how can we
assume that since there is not enough
memory to allocate an object (Eg. a
new int), there will be enough memory
to store an exception ??

No, usually the standard libraries will ensure, usually by allocating a small amount of memory in advance, that there will be enough memory for an exception to be raised in the event that memory is exhausted.

Using new and be able to check the pointer for 0 (null)

Read the doc: http://www.cplusplus.com/reference/new/operator%20new/

(2) nothrow allocation
Same as above (1), except that on failure it returns a null pointer instead of throwing an exception.

As well as example:

  std::cout << "2: ";
MyClass * p2 = new (std::nothrow) MyClass;
// allocates memory by calling: operator new (sizeof(MyClass),std::nothrow)
// and then constructs an object at the newly allocated space

std::nothrow pretty much useless?

std::nothrow means that instead of std::bad_alloc being thrown on failure to acquire memory, the new expression returns nullptr. It does not mean that the new expression will not ever throw.

If your SomeStruct did not throw in its constructor, the new expression would never throw.

Operator new with nothrow option still throws exception

I just ran your sample from VC2010. It is not new(nothrow) that throws, but __security_check_cookie.



Related Topics



Leave a reply



Submit