Reputation: 38092
Basically when class has alignment requirement and custom operators new[]
and delete[]
, then on gcc bad things happen and address sanitizer reports buffer overflow:
#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);
}
}
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]
Note that s
value for Foo[]
doesn't match for new[]
and delete[]
operations.
Address sanitizer reports buffer overflow.
clang is fine
Its there a way to fix this problem? For example add some compiler flag (there is see edit section below).
Is this a known issue? I do not know how to find respective bug report for that (IMO it is gcc bug).
Ok I have a workaround. Adding explicit destructor ~Foo() {}
fixes this issue: https://godbolt.org/z/WoM91Y (use of ~Foo() = default;
doesn't fix it).
Upvotes: 4
Views: 360
Reputation: 4062
Interestingly enough, adding default non-inline destructor (Foo::~Foo()=default;
) fixes the problem too.
Upvotes: 1