【问题标题】:Why does not std::nothrow work as expected in gcc(4.9)?为什么 std::nothrow 在 gcc(4.9) 中不能按预期工作?
【发布时间】:2016-09-27 17:49:18
【问题描述】:

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

    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 中应该如何检查 new 运算符返回的指针

【问题讨论】:

  • 它在 clang 中按预期工作
  • 是的!它也适用于 vc++ 编译器。但我不知道为什么它不能在 gcc 中工作。
  • 使用GCC 6.1.0 除非您将大小减小到合法数量,否则它不会编译。然后它按预期工作。
  • @Galik 我怎样才能知道法律限制是多少?你知道它在 gcc 4.9 中有多大吗?

标签: c++ g++


【解决方案1】:

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

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++ 版本,因为在那些标记为constexprstd::numeric_limits&lt;long long&gt;::max() 中是一个核心常量表达式,这会产生编译时错误。

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

【讨论】:

  • 谢谢!我将 nullptr 改回 NULL 并编译了没有“-std=c++11”选项的代码。这次它确实按预期工作。最现代的 c++ 是如此不同,我有很多东西要学。
猜你喜欢
  • 2019-02-14
  • 1970-01-01
  • 2020-06-07
  • 2021-05-30
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多