CWARN.MEM.NONPOD

Memory manipulation routine applied to a non-POD object

Low level memory manipulation routines (memset, bzero, memcpy, etc.) should be never used for initializing objects of non-POD (plain old data) types. Such objects should be initialized by means of their constructors.

Vulnerability and risk

If an object is non-POD, it normally contains information different from plain data. Writing directly to memory occupied by such an object will most likely corrupt its internal memory representation. In particular, the vtable of the object itself or of one of its members may be lost, and an attempt to call a virtual member function may therefore cause a crash. Rewriting reference members directly will also cause a failure when those members are used.

Example

struct XXX {
  int x, y;
};

struct A
{
  int a;
  vector<XXX> b;
};

void foo() {
  struct A aaa;
  memset(&aaa, 0, sizeof(aaa));        // DEFECT
  struct A *paaa = (struct A *)malloc(sizeof(struct A));
  memset(paaa, 0, sizeof(struct A));   // DEFECT
  struct XXX xxx;
  memset(&xxx, 0, sizeof(struct XXX)); // OK - struct XXX is POD
}

To fix this example, remove erroneous memset's and add a constructor to struct A instead. If you allocate memory for your object with malloc or other allocators that do not invoke constructors, use placement "new":

struct XXX {
  int x, y;
};

struct A
{
  int a;
  vector<XXX> b;

  A() : a(0) {}
};

void foo() {
  struct A aaa;
  void *paaa_memory = malloc(sizeof(struct A));
  struct A *paaa = new (paaa_memory) A;
  struct XXX xxx;
  memset(&xxx, 0, sizeof(struct XXX));
}