c++ - 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);
}
}
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;
不能解决此问题)。
解决方案
有趣的是,添加默认的非内联析构函数 ( Foo::~Foo()=default;
) 也解决了这个问题。
推荐阅读
- signalr - 我们从信号器集线器收到的数据类型是什么?
- github - 如何通过命令行在GitHub上发布并附加一个大文件?
- c - 在 C 中的 BST 中查找并删除错误的节点
- android - 在 Android 项目中使用 AbstractProjectConfig
- php - 为什么我的联系表格会重定向到空白页面?
- ios - 如何在 SwiftUI 中为文本的折叠设置动画
- node.js - NodeJS + TypeScript 错误 TS2339:“性能”类型上不存在属性“timeOrigin”
- sql - 查找唯一标识符重复的每个字段的最大序列号
- html - Css flex对齐问题
- d3.js - 如何使用事件侦听器来切换我的 d3 条形图,我只能看到一个而不是两个?