new(std::nothrow) int[n] 抛出异常

Posted

技术标签:

【中文标题】new(std::nothrow) int[n] 抛出异常【英文标题】:new(std::nothrow) int[n] throws an exception 【发布时间】:2019-12-19 17:51:45 【问题描述】:
#include <iostream>
#include <new>

int main()

    int n = -1;
    try
    
        int *p = new(std::nothrow) int[n];
        if(!p)
            std::cout << "new expression returned nullptr\n";
    
    catch(const std::bad_array_new_length& e)
    
        std::cout << "new expression threw " << e.what() << std::endl;
    

为什么这段代码会抛出异常?它打印new expression threw std::bad_array_new_length。 根据标准,在这种情况下,新表达式应返回 nullptr。

如果 noptr-new-declarator 中的表达式存在,它是 隐式转换为 std::size_t。如果出现以下情况,则表达式错误:

——表达式是非类类型,它在转换为之前的值 std::size_t 小于零;

[...]

如果表达式错误 转换为 std::size_t 后:

——如果表达式是核心 常量表达式,程序格式错误;

——否则,一个 不调用分配函数;而是

——如果分配 本来会被调用的函数有一个非抛出异常 规范(14.5),新表达式的值为空 所需结果类型的指针值;

——否则, new-expression 通过抛出一个类型的异常来终止 将匹配 std::bad_array_new_length 类型的处理程序 (14.4) (17.6.3.2)。

使用 gcc 9.2 编译

【问题讨论】:

归档gcc bug 93016。 嗯。顺便说一句,“转换为 std::size_t 之后”看起来是错误的。也许是标准委员会的编辑错误? 这是Core issue 1992。 @T.C.它应该抛出还是一个错误?我从文本中没有理解这一点。 @Lassie 核心问题表明抛出异常曾经是标准中的一个错误。 【参考方案1】:

我怀疑这是 libstdc++ 中的一个错误;使用 clang 和 libc++ 运行此代码会打印“新表达式返回 nullptr”

【讨论】:

libstdc++ 的错误?几乎没有,这在编译器中。 @Deduplicator - 我不这么认为。看看the libc++ implementation 这表明他们的 nothrow op-new 函数正确地吞下了所有异常。但是到那时,人们再也无法检查是否超出了实施限制或负输入,那列火车早就离开了车站。因此,这里无关紧要。 是的,这不是图书馆的问题。

以上是关于new(std::nothrow) int[n] 抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

std::nothrow

nothrow 还是异常?

全局关闭 C++ 新运算符异常

new和malloc申请内存失败后的处理

手动调用析构函数总是一个糟糕的设计标志?

cocos2d 源码分析----Node create