Will new return NULL in any case?

﹥>﹥吖頭↗ 提交于 2019-11-26 14:33:12
Michael Burr

VC6 was non-compliant by default in this regard. VC6's new returned 0 (or NULL).

Here's Microsoft's KB Article on this issue along with their suggested workaround using a custom new handler:

If you have old code that was written for VC6 behavior, you can get that same behavior with newer MSVC compilers (something like 7.0 and later) by linking in a object file named nothrownew.obj. There's actually a fairly complicated set of rules in the 7.0 and 7.1 compilers (VS2002 and VS2003) to determine whether they defaulted to non-throwing or throwing new.

It seems that MS cleaned this up in 8.0 (VS2005)—now it always defaults to a throwing new unless you specifically link to nothrownew.obj.

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

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

This appears to work in VC6, so it could 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.

I'd like to add the (somewhat controversial) opinion that checking for NULL after an allocation attempt is pretty much an exercise in futility. If your program ever runs into that situation, chances are you can't do much more than exiting fast. It's very likely that any subsequent allocation attempt will also fail.

Without checking for NULL, your subsequent code would attempt to dereference a NULL pointer, which tends to exit the program fast, with a relatively unique (and easily debuggable) exit condition.

I'm not trying to talk you out of checking for NULL, it's certainly conscientious programming. But you don't gain much from it, unless in very specific cases where you can perhaps store some recovery information (without allocating more memory), or free less important memory, etc. But those cases will be relatively rare for most people.

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

Based on the C++ spec, it will always throw std::bad_alloc when you use just plain new with no params, but of course there can be some non compliant compilers.

I would not code to be compliant with non c++ compliant compilers though. VC6 being one of them in this respect.

It is good practice though to always set your pointer to NULL after you delete them. So because of that, checking for NULL is still needed.

That being said, here are a couple options to cleaning up your code:

Option 1: Setting your own new handler

A safe way to clean up your code would be to call: set_new_handler first.

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

If you like exceptions better, then this is your best bet. If you like to return NULL better then you can also do that by doing a catch inside your new handler.

Option 2: Using overloaded new

The c++ standard header file defines a struct nothrow which is empty. You can use an object of this struct inside new to get its overloaded version that 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 refrence for further reading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!