インライン制約が守られていません
const でない静的変数が非静的インライン関数で変更される
説明
この欠陥は、非静的インライン関数で、ファイル スコープの非 const 静的変数を参照した場合や、ローカルの非 const 静的変数を定義した場合に発生します。
たとえば、var は、inline 関数 func 内で定義された非 const の static 変数です。g_step は、同じインライン関数内で参照先となるファイル スコープの非 const 静的変数です。
static int g_step;
inline void func (void) {
static int var = 0; // Defect
var += g_step; // Defect
}リスク
非静的インライン関数で非 const 静的変数を変更すると、予期しない誤った結果が生じる可能性があります。file2.cpp 内でインライン関数として使用する extern 関数 func() について考えます。この関数はインラインでない場合、file1.cpp 内で指定されるため、この関数には外部定義があります。
// file1.c
void func(void) {
static var1 = 0;
var2 = 0;
var1++;
var2++;
} | // file2.c
extern inline void func(void) {
static var1 = 0;
var2 = 0;
var1++;
var2++;
} |
func() が非 const 静的変数を変更した場合、関数の動作が予測不能になります。func() を呼び出した場合、コンパイラはこの関数のインライン バージョンと非インライン バージョンのどちらでも呼び出すことができます。ISO®/IEC 9899:2011 の節6.7.4 を参照してください。func() に対して複数の呼び出しを行った場合、同じ静的変数 var1 が変更されない可能性があります。これは予期しない動作であり、誤った結果につながるおそれがあります。
修正方法
次のいずれかの修正方法を使用します。
変数を変更する意図がない場合は、変数を
constとして宣言する。変数を変更しなければ、予期しない変更の問題は起こりません。
変数を非
staticにする。宣言からstatic修飾子を削除します。変数が関数内で定義されている場合、その変数は標準ローカル変数になります。ファイル スコープで定義されている場合は extern 変数になります。
関数を
staticにする。static修飾子を関数定義に追加します。関数を
staticにすれば、インライン定義のあるファイルでは関数を呼び出すときに常にインライン定義が使用されます。他のファイルでは関数の別の定義が使用されます。どの関数定義が使用されるかという問題が、コンパイラ任せでなくなります。
例
結果情報
| グループ: プログラミング |
| 言語: C | C++ |
| 既定値: 手書きコードはオン、生成コードはオフ |
コマンド ライン構文: INLINE_CONSTRAINT_NOT_RESPECTED |
| 影響度: Medium |