C++ 在任何情况下 new 都会返回 NULL 吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/550451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:54:17  来源:igfitidea点击:

Will new return NULL in any case?

c++visual-c++memory-managementnew-operatorvisual-c++-6

提问by Naveen

I know that according to C++ standard in case the new fails to allocate memory it is supposed to throw std::bad_alloc exception. But I have heard that some compilers such as VC6 (or CRT implementation?) do not adhere to it. Is this true ? I am asking this because checking for NULL after each and every new statement makes code look very ugly.

我知道根据 C++ 标准,如果 new 无法分配内存,它应该抛出 std::bad_alloc 异常。但我听说有些编译器如 VC6(或 CRT 实现?)不遵守它。这是真的 ?我问这个是因为在每个新语句之后检查 NULL 会使代码看起来非常难看。

回答by Michael Burr

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

在这方面,默认情况下 VC6 是不合规的。VC6new返回0(或NULL)。

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

这是微软关于这个问题的知识库文章以及他们建议的使用自定义new处理程序的解决方法:

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 rulesin the 7.0 and 7.1 compilers (VS2002 and VS2003) to determine whether they defaulted to non-throwing or throwing new.

如果您有为 VC6 行为编写的旧代码,则可以通过链接名为nothrownew.obj. 在 7.0 和 7.1 编译器(VS2002 和 VS2003)中实际上有一组相当复杂的规则来确定它们是默认为 non-throwing 还是 throwing new

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

似乎MS在 8.0 (VS2005) 中对此进行了清理-现在,除非您专门链接到nothrownew.obj.

Note that you can specify that you want newto return 0instead of throwing std::bad_allocusing the std::nothrowparameter:

请注意,您可以使用参数指定要new返回0而不是抛出:std::bad_allocstd::nothrow

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.

这似乎在 VC6 中有效,因此它可能是一种或多或少机械地修复代码以与所有编译器相同的方法,因此您不必重新处理现有的错误处理。

回答by Naveen

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.

我想补充一个(有点争议的)观点,即在尝试分配后检查 NULL 几乎是徒劳的。如果您的程序遇到过这种情况,您可能只能快速退出。任何后续的分配尝试也很可能会失败。

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.

如果不检查 NULL,您的后续代码将尝试取消引用 NULL 指针,这往往会以相对独特(且易于调试)的退出条件快速退出程序。

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.

我不是要劝你不要检查 NULL,这当然是认真的编程。但是您不会从中获得多少收益,除非在非常特殊的情况下,您可能可以存储一些恢复信息(无需分配更多内存),或释放不太重要的内存等。但这些情况对大多数人来说相对较少。

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

鉴于此,我只是相信编译器会亲自抛出 bad_alloc - 至少在大多数情况下。

回答by Brian R. Bondy

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.

基于 C++ 规范,当您只使用没有参数的普通 new 时,它总是会抛出 std::bad_alloc ,但当然可能有一些不兼容的编译器。

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

不过,我不会编写与非 C++ 兼容编译器兼容的代码。在这方面,VC6 就是其中之一。

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.

尽管在删除指针后始终将指针设置为 NULL,但这是一种很好的做法。因此,仍然需要检查 NULL。

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

话虽如此,这里有几个清理代码的选项:

Option 1: Setting your own new handler

选项 1:设置您自己的新处理程序

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

一种清理代码的安全方法是先调用:set_new_handler

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

然后,您可以在处理程序中检查 NULL 并在返回 NULL 时将 std::bad_alloc 扔到那里。

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.

如果你更喜欢例外,那么这是你最好的选择。如果您想更好地返回 NULL,那么您也可以通过在新处理程序中执行 catch 来实现。

Option 2: Using overloaded new

选项 2:使用重载的 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.

C++ 标准头文件定义了一个空的结构体 nothrow。您可以在 new 中使用此结构的对象来获取其始终返回 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

这是进一步阅读的好参考