为什么std :: nothrow在gcc(4.9)中按预期工作? [英] Why does not std::nothrow work as expected in gcc(4.9)?

查看:144
本文介绍了为什么std :: nothrow在gcc(4.9)中按预期工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  SomeClass * pSc = new SomeClass;我的团队中有很多人检查这样的空指针。 
if(NULL == pSc)
{
//应付错误
}

我知道这是行不通的,因为c ++中的new运算符抛出std :: bad_alloc异常而不返回NULL。我也知道std :: nothrow可以使他们预期的真正发生。所以我写了一个这样的例子:

  #include< iostream> 
#include< limits>
#include< new>
使用namespace std;

void myNewHandler()
{
std :: cerr<< 无法分配内存! <<的std :: ENDL;

$ b $ 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<< 分配失败<<的std :: ENDL;
返回-1;
}
else
{
delete [] pLotsMem;
pLotsMem = nullptr;
}

// std :: set_new_handler(oldHandler);

返回0;
}

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



任何想法为什么这不起作用? gcc中新操作符返回的指针应该如何检查?

解决方案

相信与否,这是符合标准的行为:


5.3.4 / 7



noptr-new-declarator在以下情况下是错误的:

[...] - 它的值使分配对象的大小超过实现定义的限制<附件B>;或

[...]



如果表达式在转换为std :: size_t后是一个核心不断
表达式和表达是错误的,该程序是格式不正确。
否则,带有错误表达式的新表达式不会
调用分配函数并终止抛出
a类型的异常,该异常匹配$类型的处理程序(15.3) b $ b std :: bad_array_new_length
(18.6.2.2)。当
表达式的值为零时,将调用分配函数来分配一个没有元素的
数组。




简而言之,非抛出分配器函数甚至没有被调用,异常是由 new-expression 本身抛出的。



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



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


I've seen lots of people in my team checking null pointers like this:

    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. I also know that std::nothrow can make what they expected really happen. 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. 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.

Any idea why this failed to work? How should one check pointers returned by new operator in gcc?

解决方案

Believe or not, this is standard compliant behavior:

5.3.4/7

The expression in a noptr-new-declarator is erroneous if:
[...] — its value is such that the size of the allocated object would exceed the implementation-defined limit (annex 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. 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). 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.

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.

Clang, probably has implementation-defined limit set higher than max value of long lond, bypassing this quirk of C++.

这篇关于为什么std :: nothrow在gcc(4.9)中按预期工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆