EN JP CN

CWARN.MEM.NONPOD

CWARN.MEM.NONPOD

非 POD オブジェクトに適用されるメモリ操作ルーチン

低レベルのメモリ操作ルーチン (memset、bzero、memcpy など) は、POD (plain old data) タイプ以外のオブジェクトの初期化には決して使用しないでください。このようなオブジェクトは、そのコンストラクタを使用することで初期化してください。

脆弱性とリスク

POD 以外のオブジェクトの場合、通常は、プレーンデータとは異なる情報を格納します。そのようなオブジェクトが占有するメモリに直接書き込むと、その内部メモリ表現が破壊される可能性があります。特に、オブジェクト自体か、またはそのいずれかのメンバーの vtable が失われる場合があり、そのため仮想メンバー関数を呼び出す試みがクラッシュを引き起こす可能性があります。リファレンスメンバーを再度、直接書き込むと、それらのメンバーの使用時に障害の原因となる場合もあります。

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));
}