简体   繁体   English

为什么std :: nothrow无法按gcc(4.9)的预期工作?

[英]Why does not std::nothrow work as expected in gcc(4.9)?

I've seen lots of people in my team checking null pointers like this: 我在团队中看到很多人都在检查null指针,如下所示:

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

I known this will not work, because new operator in c++ throws a std::bad_alloc exception instead of returning NULL. 我知道这是行不通的,因为c ++中的new运算符会抛出std :: bad_alloc异常,而不是返回NULL。 I also know that std::nothrow can make what they expected really happen. 我也知道std :: nothrow不能使他们的期望真正实现。 So I wrote an example like this: 所以我写了一个这样的例子:

    #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;
    } 

Yes, I wanted to demonstrate usage of std::set_new_handler as well. 是的,我也想演示std :: set_new_handler的用法。 To my surprise, even this did not work. 令我惊讶的是,即使这样也没有用。 new operator still threw an exception(std::bad_array_new_length, a derived class of std::bad_alloc) and then terminated the program. 新操作符仍然引发异常(std :: bad_array_new_length,std :: bad_alloc的派生类),然后终止程序。

Any idea why this failed to work? 知道为什么这行不通吗? How should one check pointers returned by new operator in gcc ? gcc中的new运算符应如何返回一个检查指针

Believe or not, this is standard compliant behavior: 信不信由你,这是符合标准的行为:

5.3.4/7 5.3.4 / 7

The expression in a noptr-new-declarator is erroneous if: 如果满足以下条件,则noptr-new-declarator中的表达式是错误的:
[...] — its value is such that the size of the allocated object would exceed the implementation-defined limit (annex B); [...]其值使得所分配对象大小将超过实现定义的限制 (附件B); or 要么
[...] [...]

If the expression, after converting to std::size_t, is a core constant expression and the expression is erroneous, the program is ill-formed. 如果该表达式在转换为std :: size_t之后是核心常量表达式,并且该表达式错误,则表明程序格式错误。 Otherwise, a new-expression with an erroneous expression does not call an allocation function and terminates by throwing an exception of a type that would match a handler (15.3) of type std::bad_array_new_length (18.6.2.2). 否则, 带有错误表达式new表达式不会调用分配函数,并且会引发抛出异常,该异常将与std :: bad_array_new_length (18.6.2.2) 类型的处理程序(15.3)匹配 When the value of the expression is zero, the allocation function is called to allocate an array with no elements. 当表达式的值为零时,将调用分配函数以分配不包含任何元素的数组。

In short, non-throwing allocator function is not even called, exception is thrown by new-expression itself. 简而言之,甚至不调用非抛出分配器函数, new-expression本身会抛出异常。

I assume that you are not using modern C++ version, because in those std::numeric_limits<long long>::max() marked as constexpr and is a core constant expression , which yields compile-time error. 我假设您没有使用现代的C ++版本,因为在那些标为constexpr std::numeric_limits<long long>::max() ,它是一个核心常量表达式 ,会产生编译时错误。

Clang, probably has implementation-defined limit set higher than max value of long lond, bypassing this quirk of C++. Clang 可能实现定义的限制设置为高于long lond的最大值,从而绕过了C ++的这个怪癖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM