C & C++

C & C++

Made by DeepSource

Found using default opertor new for over-aligned types CXX-W2018

Bug risk
Major

The global operator new is called it allocates storage for any object of the specified size, and it is only guaranteed to have a suitable alignment for objects with a fundamental alignment requirement, and not for over-aligned types. One can specify the alignment requirement while declaring a C++ record using the keyword alignas as shown in the examples below. Such C++ records, with user-specified alignment, are called over-aligned types.

It is recommended that one should implement the operator new() for over-aligned types and avoid using the default implementation of new. This is because such a practice could cause the objects to be constructed at a location that is misaligned, which is an undefined behavior and can lead to abnormal termination when the object is accessed. This risk remains even on architectures that are otherwise capable of tolerating misaligned accesses.

Bad practice

struct alignas(128) ARecord {
  char elems[128];
};

ARecord* getRecords() {
  ARecord *pv = new ARecord; // A misaligned memory allocation
  return pv;
}

Recommended

#include <cstdlib>
#include <new>

struct alignas(128) ARecord {
  char elems[128];
  static void *operator new(size_t nbytes) {
    if (void *p = std::aligned_alloc(alignof(ARecord), nbytes)) {
      return p;
    }
    throw std::bad_alloc();
  }
  static void operator delete(void *p) {
    free(p);
  }
};

ARecord *f() {
  // A call to overloaded operator `new` to make sure the alignment is okay
  ARecord *pv = new ARecord;
  return pv;
}

References