メインコンテンツ

C++ の offsetof の誤った使用

offsetof マクロの不適切な引数による未定義の動作の発生

説明

この欠陥は、動作が定義されていない offsetof マクロに引数が渡された場合に発生します。

offsetof マクロ:

offsetof(classType, aMember)
これは、classType 型のオブジェクトの先頭からのデータ メンバー aMember のオフセットをバイト単位で返します。offsetof で使用する場合、classTypeaMember には一定の制限があります。

  • classType は標準レイアウト クラスでなければならない。

    たとえば、メンバー関数 virtual を含んでいてはなりません。標準レイアウト クラスの要件の詳細は、C++ named requirements: StandardLayoutType を参照してください。

  • aMember は静的であってはならない。

  • aMember はメンバー関数であってはならない。

チェッカーは、引数がこれらの 1 つ以上の制限に違反している場合、offsetof マクロの使用にフラグを設定します。

リスク

offsetof マクロの引数の制限に違反すると未定義の動作につながります。

修正方法

offsetof マクロは、標準レイアウト クラスの非静的データ メンバーに対してのみ使用します。

結果の詳細に、offsetof マクロのどの制限に違反しているかが示されます。その違反を修正します。

すべて展開する

#include <cstddef>

class myClass {
     int member1;
  public:
     int member2;
};

void func() {
  size_t off = offsetof(myClass, member2);
  // ...
}

この例では、クラス myClass にはアクセス制御が異なる 2 つのデータ メンバーがあり、一方はプライベートで他方はパブリックです。そのため、このクラスは標準レイアウト クラスの要件を満たさず、offsetof マクロと共に使用できません。

修正 — すべてのデータ メンバーで同一のアクセス制御を使用

アプリケーションにおいて offsetof の使用が重要な場合、最初の引数が標準レイアウトのクラスであることを確認します。たとえば、パブリック データ メンバーの必要性を回避できるか確認します。

#include <cstddef>
  
class myClass {
     int member1;
     int member2;
  public:
     int getMember2(void) { return member2;}
     friend void func(void);
};
  
void func() {
  size_t off = offsetof(myClass, member2);
  // ...
}

結果情報

グループ: プログラミング
言語: C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: OFFSETOF_MISUSE
影響度: Medium

バージョン履歴

R2019a で導入