Clang在分配超过限制的对象时无法抛出std :: bad_alloc [英] Clang fails to throw a std::bad_alloc when allocating objects that would exceed the limit

查看:307
本文介绍了Clang在分配超过限制的对象时无法抛出std :: bad_alloc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试分配超过其限制的对象时,我无法理解clang引发异常。例如,如果我编译并运行下面的代码:

I am having trouble understanding how clang throws exceptions when I try to allocate an object that would exceed its limit. For instance if I compile and run the following bit of code:

#include <limits>
#include <new>
#include <iostream>

int main(int argc, char** argv) {
    typedef unsigned char byte;
    byte*gb;
    try{
        gb=new byte[std::numeric_limits<std::size_t>::max()];
    }
    catch(const std::bad_alloc&){
        std::cout<<"Normal"<<std::endl;
        return 0;}
    delete[]gb;
    std::cout<<"Abnormal"<<std::endl;
    return 1;
}

那么当我使用clang ++ -O0 -std = c ++ 11 main.cpp,我得到的结果是正常按照预期,但一旦我启用优化1到3,程序意外返回异常

then when I compile using "clang++ -O0 -std=c++11 main.cpp" the result I get is "Normal" as expected, but as soon as I enable optimizations 1 through 3, the program unexpectedly returns "Abnormal".

我说意外,因为根据C ++ 11标准5.3.4.7:

I am saying unexpectedly, because according to the C++11 standard 5.3.4.7:


当noptr-new-declarator中的表达式的值为零时,分配函数调用
分配没有元素的数组。如果该表达式的值小于零或者使得所分配对象的大小
将超过实现定义的限制
,或者如果新初始化器是大括号
init-list,其中initializer-clause的数量超过要初始化的元素的数量,没有存储
并且 new-expression通过抛出将匹配$的类型的异常终止

When the value of the expression in a noptr-new-declarator is zero, the allocation function is called to allocate an array with no elements. If the value of that expression is less than zero or such that the size of the allocated object would exceed the implementation-defined limit, or if the new-initializer is a braced- init-list for which the number of initializer-clauses exceeds the number of elements to initialize, no storage is obtained and the new-expression 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).

[此行为是属于std :: bad_array_new_length(18.6.2.2)的b $ b处理程序观察到与clang 3.5使用libstd ++在linux和clang 3.3使用libc ++在Mac上。当删除-std = c ++ 11标志时,也会看到相同的行为。]

[This behavior is observed with both clang 3.5 using libstd++ on linux and clang 3.3 using libc++ on Mac. The same behavior is also observed when the -std=c++11 flag is removed.]

使用 gcc 4.8编译同一程序时, ,使用完全相同的命令行选项。在这种情况下,程序会为任何所选的优化级别返回正常

The plot thickens when I compile the same program using gcc 4.8, using the exact same command line options. In that case, the program returns "Normal" for any chosen optimization level.

在上面发布的代码中找不到任何未定义的行为将解释为什么clang会自由地不启动代码优化时抛出异常。至于bug数据库,最近我可以找到的是 http:// llvm。 org / bugs / show_bug.cgi?id = 11644 ,但它似乎与抛出的异常类型有关,而不是调试和发布代码之间的行为差​​异。

I cannot find any undefined behavior in the code posted above that would explain why clang would feel free not to throw an exception when code optimizations are enabled. As far as the bug database is concerned, the closest I can find is http://llvm.org/bugs/show_bug.cgi?id=11644 but it seems to be related to the type of exception being thrown rather than a behavior difference between debug and release code.

所以这是一个来自Clang的错误?还是我错过了什么?非常感谢,

So it this a bug from Clang? Or am I missing something? Thanks,

推荐答案

看起来clang消除了数组未使用的分配:

It appears that clang eliminates the allocation as the array is unused:

#include <limits>
#include <new>
#include <iostream>

int main(int argc, char** argv)
{
    typedef unsigned char byte;
    bytes* gb;
    const size_t max = std::numeric_limits<std::size_t>::max();
    try
    {
        gb = new bytes[max];
    }
    catch(const std::bad_alloc&)
    {
        std::cout << "Normal" << std::endl;
        return 0;
    }
    try
    {
        gb[0] = 1;
        gb[max - 1] = 1;
        std::cout << gb[0] << gb[max - 1] << "\n";
    }
    catch ( ... )
    {
        std::cout << "Exception on access\n";
    }
    delete [] gb;
    std::cout << "Abnormal" << std::endl;
    return 1;
}

此代码打印Normal与-O0和-O3,请参阅此演示。这意味着在这段代码中,它实际上尝试分配内存,它的确失败,因此我们得到异常。注意,如果我们不输出,clang仍然足够聪明,甚至忽略写入。

This code prints "Normal" with -O0 and -O3, see this demo. That means that in this code, it is actually tried to allocate the memory and it indeed fails, hence we get the exception. Note that if we don't output, clang is still smart enough to even ignore the writes.

这篇关于Clang在分配超过限制的对象时无法抛出std :: bad_alloc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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