首页 > 解决方案 > Gcc 自定义运算符 new[] 和 delete[] 对于对齐的类有错误 - 地址清理程序报告缓冲区溢出

问题描述

基本上,当类有对齐要求和自定义运算符时new[]delete[]然后在 gcc 上发生坏事并且地址清理程序报告缓冲区溢出:

MCVE:

#include <iostream>
#include <memory>

class EndlineOnDone {
    std::ostream& out;
public:
    EndlineOnDone(std::ostream& out) : out{out} {}
    ~EndlineOnDone()
    {
        out << std::endl;
    }
    std::ostream& stream() { return out; }
};

#define VAR(x) " " #x "=[" << x << "]" 
#define LOG EndlineOnDone(std::cout).stream() << __PRETTY_FUNCTION__

std::ostream& operator<<(std::ostream& out, std::align_val_t a)
{
    return out << static_cast<size_t>(a);
}

class alignas(32) Foo
{
public :
    double x, y, z;

    void * operator new (size_t s, std::align_val_t a)
    {
        auto p = aligned_alloc(static_cast<size_t>(a), s);
        LOG << VAR(p) << VAR(s) << VAR(a);
        return p;
    }

    void operator delete (void * p, size_t s, std::align_val_t a)
    {
        LOG << VAR(p) << VAR(s) << VAR(a);
        if (p) free(p);
    }

#if 1
    void * operator new[ ] (size_t s, std::align_val_t a)
    {
        auto p = aligned_alloc(static_cast<size_t>(a), s);
        LOG << VAR(p) << VAR(s) << VAR(a);
        return p;
    }

    void operator delete[ ] (void *p, size_t s, std::align_val_t a)
    {
        LOG << VAR(p) << VAR(s) << VAR(a);
        if (p) free(p);
    }
#endif
};

int main()
{
    {
        LOG << " std::make_unique<Foo>";
        auto p = std::make_unique<Foo>();
    }

    {
        LOG << " std::make_unique<Foo[]>";
        auto p = std::make_unique<Foo[]>(3);
    }
}

https://godbolt.org/z/7xd8YM

gcc 日志(无地址清理程序):

int main() std::make_unique<Foo>
static void* Foo::operator new(size_t, std::align_val_t) p=[0x21d6ec0] s=[32] a=[32]
static void Foo::operator delete(void*, size_t, std::align_val_t) p=[0x21d6ec0] s=[32] a=[32]
int main() std::make_unique<Foo[]>
static void* Foo::operator new [](size_t, std::align_val_t) p=[0x21d6f40] s=[96] a=[32]
static void Foo::operator delete [](void*, size_t, std::align_val_t) p=[0x21d6f40] s=[3616] a=[32]

请注意,s值 for与操作Foo[]不匹配。new[]delete[]

地址清理程序报告缓冲区溢出。

叮当很好

问题

它有办法解决这个问题吗?例如添加一些编译器标志(参见下面的编辑部分)。

这是一个已知的问题?我不知道如何找到相应的错误报告(IMO 它是 gcc 错误)。

编辑/线索

好的,我有一个解决方法。添加显式析构函数~Foo() {}可解决此问题:https ://godbolt.org/z/WoM91Y (使用~Foo() = default;不能解决此问题)。

标签: c++gccc++17memory-alignment

解决方案


有趣的是,添加默认的非内联析构函数 ( Foo::~Foo()=default;) 也解决了这个问题。


推荐阅读