Will the new return be NULL anyway?

I know that according to the C ++ standard, if a new one cannot allocate memory, it should throw a std :: bad_alloc exception. But I heard that some compilers, such as VC6 (or CRT implementation?), Do not adhere to this. It's true? I ask about this because checking for NULL after each new statement makes the code very ugly.

+44
c ++ memory-management new-operator visual-c ++ vc6
Feb 15 '09 at 7:10
source share
3 answers

VC6 did not meet the requirements by default. VC6 new returned 0 (or NULL ).

Here's a Microsoft KB article on this subject along with a suggested workaround using the new custom handler:

If you have old code that was written for VC6 behavior, you can get the same behavior with newer MSVC compilers (for example, 7.0 and newer) by linking them in an object file called nothrownew.obj . It’s actually a rather complicated set of rules in compilers 7.0 and 7.1 (VS2002 and VS2003) to determine if they didn’t drop or drop new by default.

It looks like MS cleared this in 8.0 (VS2005) - now it always uses the meta-new by default, unless you reference nothrownew.obj .

Note that you can specify that you want new to return 0 instead of throwing std::bad_alloc using the std::nothrow :

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

This seems to work in VC6, so it may be a way to more or less mechanically fix the code to work the same with all compilers, so you don't have to rework existing error handling.

+47
Feb 15 '09 at 7:16
source share
β€” -

I would like to add a somewhat (controversial) opinion that checking for NULL after trying to isolate is largely an exercise in futility. If your program ever cope with this situation, most likely you cannot do much more than exit quickly. It is very likely that any subsequent allocation attempt will also fail.

Without checking for NULL, your subsequent code will try to dereference the NULL pointer, which tends to exit the program quickly, with a relatively unique (and easily debugged) termination condition.

I am not trying to tell you about NULL checking, this is certainly good programming. But you do not get many advantages from this, if only in special cases, where you can store some information about recovery (without allocating more memory) or free less important memory, etc. But for most people, these cases will be relatively rare.

Given this, I simply trust the compiler to personally throw bad_alloc - at least in most cases.

+19
Feb 15 '09 at 9:18
source share

Based on the C ++ specification, it will always call std :: bad_alloc when you use just the new without parameters, but of course there may be some inappropriate compilers.

I would not code to be compatible with compilers that are not compatible with C ++. VC6 is one of them in this regard.

This is good practice, although always pointing your pointer to NULL after they are removed. Therefore, because of this, NULL checking is still necessary.

As the saying goes, here are a couple of options for cleaning up your code:

Option 1: Install Your Own New Handler

A safe way to clear code would be: set_new_handler .

Then you can check for NULL in your handler and throw std :: bad_alloc there if NULL is returned.

If you prefer exceptions, then this is your best bet. If you like returning NULL better, you can also do this by catching inside your new handler.

Option 2: using an overloaded new

The standard C ++ header file defines a struct nothrow that is empty. You can use the object of this structure inside new to get your overloaded version, which always returns NULL.

 void* operator new (size_t size, const std::nothrow_t &); void* operator new[] (void *v, const std::nothrow_t &nt); 

So in your code:

  char *p = new(std::nothrow) char[1024]; 

Here is a good confirmation for further reading.

+8
Feb 15 '09 at 7:13
source share



All Articles