为什么std :: nothrow在gcc(4.9)中没有按预期工作?

时间:2016-05-30 01:20:42

标签: c++ g++

我在团队中看到很多人都在检查这样的空指针:

    SomeClass *pSc = new SomeClass;
    if ( NULL == pSc )
    {
        // cope with error
    }

我知道这不起作用,因为c ++中的new运算符抛出std :: bad_alloc异常而不是返回NULL。我也知道std :: nothrow能够达到预期的效果。所以我写了一个这样的例子:

    #include <iostream>
    #include <limits>
    #include <new>
    using namespace std;

    void myNewHandler()
    {
        std::cerr << "Failed to allocate memory!" << std::endl;
    }

    int main(int argc, char* argv[])
    {
        //std::new_handler oldHandler = std::set_new_handler(myNewHandler);

        int *pLotsMem = new(std::nothrow) int[std::numeric_limits<long long>::max()];
        if ( nullptr == pLotsMem )
        {
            std::cerr << "Allocation failed" << std::endl;
            return -1;
        }
        else
        {
            delete[] pLotsMem;
            pLotsMem = nullptr;
        }

        //std::set_new_handler(oldHandler);

        return 0;
    } 

是的,我想展示std :: set_new_handler的用法。令我惊讶的是,即使这样也行不通。 new运算符仍然抛出异常(std :: bad_array_new_length,std :: bad_alloc的派生类),然后终止该程序。

知道为什么这不起作用? 如何检查gcc中新操作符返回的指针

1 个答案:

答案 0 :(得分:4)

不管你信不信,这是符合标准的行为:

  

5.3.4 / 7

     

如果出现以下情况,则noptr-new-declarator中的表达式是错误的:
   [...] - 其值为分配对象的大小将超过实现定义的限制(附录B);或
   [...]

     

如果转换为std :: size_t后的表达式是核心常量   表达式和表达是错误的,程序是不正确的。   否则,带有错误表达式的 new-expression不会   调用分配函数并通过抛出异常终止   与类型的处理程序(15.3)匹配的类型   std :: bad_array_new_length (18.6.2.2)。当值   表达式为零,调用分配函数来分配   没有元素的数组。

简而言之,甚至不会调用非投掷分配器函数, new-expression 本身会抛出异常。

我假设您没有使用现代C ++版本,因为那些std::numeric_limits<long long>::max()标记为constexpr并且是核心常量表达式,这会产生编译时错误。

Clang,可能实现定义的限制设置为高于long lond的最大值,绕过了这个C ++的怪癖。