6

I port a middle-sized application from C to C++. It doesn't deal anywhere with exceptions, and that shouldn't change.

My (wrong!) understanding of C++ was (until I learned it the hard way yesterday) that the (default) new operator returns a NULL pointer in case of an allocation problem. However, that was only true until 1993 (or so). Nowadays, it throws a std::bad_alloc exception.

Is it possible to return to the old behavior without rewriting everything to using std::nothrow on every single call?

Roman Nikitchenko
  • 12,800
  • 7
  • 74
  • 110
dmeister
  • 34,704
  • 19
  • 73
  • 95
  • 2
    You may also be interested in reading this: http://stackoverflow.com/questions/550451/will-new-return-null-in-any-case – Naveen Nov 10 '09 at 10:08
  • 6
    Bite the bullet. Go fix your code to use std::nothrow. awk and a couple of regular expressions will get you 90% of the way there. – Martin York Nov 10 '09 at 13:19
  • +1 for really actual thing for many people despite I'm against to do such things (and I answered below why). – Roman Nikitchenko Nov 10 '09 at 14:59
  • The VC complier includes ``nothrownew.obj`` as a hack to get the old behavior, but then the behavior of the Standard C++ Library (aka STL) is undefined in the case of a failed allocation. – Chuck Walbourn Feb 18 '15 at 01:19

5 Answers5

13

You could overload operator new:

#include <vector>

void *operator new(size_t pAmount) // throw (std::bad_alloc)
{
    // just forward to the default no-throwing version.
    return ::operator new(pAmount, std::nothrow);
}

int main(void)
{
    typedef std::vector<int> container;

    container v;
    v.reserve(v.max_size()); // should fail
}
GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 1
    @GMan: In the example, the failure is not clear: is it meant to show the downside of using nothrow? – stefaanv Nov 10 '09 at 10:37
  • 3
    This will likely fail fatally. Standard containers deal with memory using allocator (by default standard allocator) and at least one of them expects exception to be thrown when there is no memory and will not check for NULL return value. Also this does not solve problem of operator new overloaded for a class. However this is unlikely problem taking into account the code is ported from C. – Adam Badura Nov 10 '09 at 13:41
  • Yea, it was meant to run "successfully" with no exceptions. And keep Adam's point in mind; you're basically re-working how `operator new` works in a failure, and some people rely on that. However, you are not one of them. :) – GManNickG Nov 10 '09 at 19:27
4

Include the header <new>. It contains a "no-throw" version of new you can use like this:

#include <new>

int main() {
    int* p = new(std::nothrow) int;
    if (p) {
        delete p;
    }
}

Edit: I admit I missed the last sentence of the question. But to be honest, I think that tweaking "plain new" to have pre-Standard behaviour isn't a good idea either. I'd look into some kind of automated search & replace to turn each new into new(std::nothrow).

sellibitze
  • 27,611
  • 3
  • 75
  • 95
1

Sorry, but as for my opinion you should NOT do this and return to old new behavior. This is because you simply can't avoid exceptions anyway.

WHY?

Consider about new call which should allocate class with constructor calling some initialization code which needs to construct anything temporary which is dynamic. Alas, you are going to have exception. No matter if you use std::nothrow. This is only one scenario among number of them.

In Scott Meyers book Effective C++ it was discussed in details as far as I remember. But I'm not sure if all the cases are reviewed (but I suggest enough of them).

Roman Nikitchenko
  • 12,800
  • 7
  • 74
  • 110
  • I use the constructor only for assignments. For anything more, I use an "bool Init()" method. – dmeister Nov 10 '09 at 16:01
  • Things always change. It could happen even after you drop support of this code and move to the other side of globe. I just noted I saw number of cases where people trusted too much in std::nothrow. But it is not magic ;-). – Roman Nikitchenko Nov 10 '09 at 20:18
1

Just try it out :

1.Define a function which you want to invoke on out of memory condition.

2.Pass this function to set_ new _handler function so when new fails this function will be called.

Ashish
  • 8,441
  • 12
  • 55
  • 92
  • 1
    I wasn't aware of it, but the standard draft says that the `new_handler` may a) make more memory available and return, b) throw `std::bad_alloc` or derived exception, c) call abort() or exit(). What you can't do is to make new return 0 instead of throwing. – UncleBens Nov 10 '09 at 20:05
0

Your compiler likely has a commandline switch to enable/disable this behaviour.

Will
  • 73,905
  • 40
  • 169
  • 246
  • 2
    a much more helpful answer would have been to actually write the commandline switch that supposedly exists, atleast for gcc and VC++. – Idan K Nov 10 '09 at 10:06