当前位置:  开发笔记 > 编程语言 > 正文

我相信这是一个与其构造函数抛出的放置new-expression相关的clang中的错误

如何解决《我相信这是一个与其构造函数抛出的放置new-expression相关的clang中的错误》经验,为你挑选了1个好方法。

当一个问题出现了新的表达形式new(std::nothrow) C;哪里C是一个类名,其构造函数抛出.使用以下代码查看下面的代码和实例g++:

#include 

void* operator new(std::size_t size, const std::nothrow_t&) noexcept
{
    void* p;
    p = malloc(size);
    std::cout << "operator new(std::nothrow)" << '\n';
    return p;
}

void operator delete(void* p, const std::nothrow_t&) noexcept
{
    free(p);
    std::cout << "operator delete(std::nothrow)" << '\n';
    std::cout << p << '\n';
}

class T{};

class C {
    int i;
public:
    C(int i) : i{i} { std::cout << "C()" << '\n'; throw T{}; }
    ~C() { std::cout << "~C()" << '\n'; }
};

int main()
{
    C* c;
    try { c = new(std::nothrow) C(3); }
    catch (T&)
    {
        std::cout << "exception thrown in C(int) was caught" << '\n';
        std::cout << c << '\n';
    }
}

g++ 打印以下内容似乎是正确的:

operator new(std::nothrow)
C()
operator delete(std::nothrow)
0x13f9c20
exception thrown in C(int) was caught
0

然而,如果您使用clang,您将获得以下输出:

operator new(std::nothrow)
C()
exception thrown in C(int) was caught
0x7fffecdeed00

也就是说,它好像clang调用operator delete(void*, std::nothrow_t&)在程序中定义,并呼吁相反,运营商在标准库.

奇怪的是,通过只删除表达式std::cout << p << '\n';operator delete(void*, std::nothrow_t&),在代码中定义的,clangs似乎正确执行,打印:

operator new(std::nothrow)
C()
operator delete(std::nothrow)
exception thrown in C(int) was caught
0x7fffc0ffc000

编辑

为了回应@TC下面的评论和其他人说上面的代码有未定义的行为,我在下面提供另一个代码,显示编译器应该如何操作,正确编译上面的代码片段,使用由以下代码提供的伪代码: @TC 在这里.另请参见此实例.要注意的重要一点是,这个代码不使用新的表达 new(nothrow).

#include 

void * operator new(std::size_t n)
{
    void* p;
    try { p = malloc(n); }
    catch (std::bad_alloc&) { throw; }
    std::cout << "operator new" << '\n';
    return p;
}

void operator delete(void *p) noexcept
{
    free(p);
    std::cout << "operator delete" << '\n';
}

void* operator new(std::size_t size, const std::nothrow_t&) noexcept
{
    void* p = malloc(size);
    std::cout << "operator new(std::nothrow)" << '\n';
    return p;
}

void operator delete(void* p, const std::nothrow_t&) noexcept
{
    free(p);
    std::cout << "operator delete(std::nothrow)" << '\n';
    std::cout << p << '\n';
}

class T {};

class C {
    int i;
public:
    C(int i) : i{ i } { std::cout << "C()" << '\n'; throw T{}; }
    ~C() { std::cout << "~C()" << '\n'; }
};

int main()
{
    C *c;
    try
    {
        c = (C*)operator new(sizeof(C), std::nothrow);
        struct cleanup
        {
            void* p;
            bool active;
            ~cleanup() { if (active) operator delete(p, std::nothrow); }
            void dismiss() { active = false; }
        } guard = { (void*)c, true };
        new(c) C{1};
        guard.dismiss();
    }
    catch ( std::bad_alloc& ) { c = nullptr; }
    catch (T&)
    {
        std::cout << "exception thrown in C() was caught" << '\n';
        std::cout << c << '\n';
    }
}

g++ 为此代码打印以下内容:

operator new(std::nothrow)
C()
operator delete(std::nothrow)
0x10c3c20
exception thrown in C() was caught
0x10c3c20

令人惊讶的是,clang似乎使用此代码正确操作,该代码不使用new-expression new(nothrow),这清楚地表明clang在编译此new-expression时存在错误.



1> Howard Hinna..:

在我的系统OS X 10.11.1上,std :: lib-provided operator delete位于/usr/lib/libc++abi.dylib中.在类Unix系统上,这个签名通过赋予它"弱连接"而可以替换.当链接器看到两个相同的签名,并且其中一个具有弱连接时,它将更喜欢那个没有的签名.

我可以确认在我的系统上,operator delete(void*, std::nothrow_t const&)与以下命令的链接很弱:

$ nm -gm /usr/lib/libc++abi.dylib |c++filt |grep nothrow_t
0000000000024406 (__TEXT,__text) weak external operator delete[](void*, std::nothrow_t const&)
00000000000243fc (__TEXT,__text) weak external operator delete(void*, std::nothrow_t const&)
00000000000243c0 (__TEXT,__text) weak external operator new[](unsigned long, std::nothrow_t const&)
000000000002437e (__TEXT,__text) weak external operator new(unsigned long, std::nothrow_t const&)

您能对系统进行类似的分析并报告结果吗?

更新

感谢TC下面关于如何复制症状的说明,它现在在我看来这是一个clang编译器代码生成错误,在3.7中引入,仍然存在于主干中,并且只能在-O2(不是-O1)重现或更低而不是-O3).

我认为错误报告是有序的,它应该有关于如何重现错误的良好指示(除非你希望它们给它一个低优先级).

PS

并设置,C *c = nullptr;以便他们不浪费时间追逐不相关的UB.

第二次更新

我仍然无法使用clang tip-of-trunk在本地重现这一点.但我可以在以下网站上看到它:

http://melpon.org/wandbox/permlink/5zIRyPJpq32LfU0t

我还没有解释这种差异.也许我的行李箱比他们的更近?也许他们没有使用libc ++ abi?

推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有