NULLize the throwing new

Old versions of Microsoft's C++ compiler supplied a form of the new keyword which would return NULL if the memory allocation failed (to mimic the behavior of malloc). The newer (more C++ compliant) versions of the compiler will instead throw a std::bad_alloc exception on failure. This change has lead to a frequent question on the internal mailing lists: "how do I get a version of new which returns NULL? " (1)

 

There are a handful of reasons to ask this, the most common is that someone is dealing with a legacy codebase which wasn't designed to be exception friendly.

 

With Visual Studio 2008, there are two answers (2): the surgical approach, or the brute force approach.

Surgical

The surgical method allows a developer to go into individual call sites and specify whether the call to new should return NULL instead of throwing an error. This is accomplished using a placement new which takes an object from the std namespace, handily called "nothrow".

 

char *s = new(std::nothrow) char[123];

if(s == NULL) ...

 

While this approach does take a certain amount of grunt work to convert a large code base, this is the best approach as you can selectively decide which calls to new return NULL or which ones remain C++ standard friendly.

Brute Force

The sledge hammer approach is really pretty simple: you just need to link nothrownew.obj into your project and all calls to the default new operator will be returned to the old NULL returning version. The drawback is that all calls are changed, so if anybody is relying on the C++ conformant version, they will not work correctly when an error does happen. For example, any code which uses the Standard Template Library will be very unhappy with the results of doing this.

 

In case my choice of words hasn't conveyed the appropriate message yet, let me be utterly clear: It is highly recommended that you do not link with nothrownew.obj. Instead, you should be using the (std::nothrow) option to explicitly state which calls to new should return NULL.

For Testers

As a tester, it is important to know about the difference here so you can spot occurrences where the code you are testing (or even writing) is doing the wrong thing.

Footnotes

(1) The fact that this topic keeps coming up means that having more information about it is a good thing.

(2) In previous versions there were more than two answers, but there is no need to muddy the waters here now that things are simpler. If you are still running VS 2003 then take a look here (vs. the same documentation for 2008).