CWARN.MEM.NONPOD

内存操作例程应用于非 POD 对象

低级内存操作例程(memset、bzero、memcpy)不得用于初始化非 POD(纯旧数据)类型的对象。这种对象应通过其构造函数进行初始化。

漏洞与风险

如果一个对象为非 POD 对象,它通常包含不同于纯数据的信息。直接写入被这种对象占用的内存很可能破坏其内部的内存表示形式。尤其,该对象本身的虚拟表或其成员之一可能丢失,因此,调用虚拟成员函数的尝试可能导致故障。如果使用这些成员,直接重写引用成员也将导致失败。

示例

复制
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
}

为修正此示例,移除错误的 memset 并向结构 A 添加一个构造函数。如果使用 malloc 或未调用构造函数的其他分配器为对象分配内存,请使用位置 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));
}