メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

ローカル変数サイズのより低い推定値

入れ子にされたスコープを考慮した関数内のローカル変数の合計サイズ

説明

このメトリクスでは、関数内のローカル変数の合計サイズの楽観的な推定値が提供されます。メトリクスは、以下のサイズのバイト単位の合計です。

  • 関数の戻り値のサイズ

  • 関数パラメーターのサイズ

  • ローカル変数のサイズ

    次のように、入れ子にされたスコープ内の変数定義が関数に含まれているものとします。

    type func (type param_1, ...) {
    
      {
        /* Scope 1 */
        type var_1, ...;
      }
      {
        /* Scope 2 */
        type var_2, ...;
      }
    }
    ソフトウェアは、各スコープ内の合計変数サイズを計算し、その中で最大のものを使用します。たとえば条件ステートメントに変数定義が含まれている場合、ソフトウェアは各分岐内の合計変数サイズを計算してから、その中で最大のものを使用します。入れ子にされたスコープ自体にさらに入れ子にされたスコープが含まれている場合は、内側のスコープに対して同じプロセスが繰り返されます。

    入れ子にされたスコープ内で定義された変数は、そのスコープ外では表示されません。そのため、一部のコンパイラは、別のスコープ内で定義された変数のスタック領域を再利用します。このメトリクスでは、このようなコンパイラのスタック使用量のより正確な推定値が提供されます。それ以外の場合は、メトリクスローカル変数サイズのより高い推定値を使用してください。このメトリクスでは、入れ子にされたスコープ内で定義されているかどうかに関係なく、すべてのローカル変数のサイズを合計します。

  • メモリ アライメントのために導入される追加パティング

ローカル変数による実際のスタック使用量は、このメトリクス値と異なる可能性があります。

  • 一部の変数はスタックではなくレジスタに保存されます。

  • コンパイラでは、メモリの一定の最適化を有効にするために、変数存続の解析が実行されます。このメトリクスを計算する際、Polyspace® ではこれらの最適化が考慮されません。

  • コンパイラでは、関数呼び出し中に追加メモリが使用されます。たとえば、コンパイラは実行で次の関数呼び出しが返る先のアドレスを保存します。このメトリクスを計算する際、Polyspace ではこの隠れたメモリの用途は考慮されません。

  • コンパイラはいくつかの方法で一時変数を最適化します。このメトリクスでは、一時変数が除外されます。ユーザーによって明示的に宣言されている変数のみが考慮されます。

ただし、このメトリクスではローカル変数によるスタック使用量の妥当な推定値が提供されます。

関数が、コピー コンストラクターを含む classstruct、または union を返す場合は、コンパイラが戻り値の最適化を実行する可能性があります。クラス オブジェクトを返す代わりに、関数は、ポインターを使用して値を渡す可能性があります。この最適化によって、このメトリクスの値が変更されることがあります。

基本型のサイズを判断するため、本ソフトウェアではターゲット プロセッサ タイプ (-target)の仕様が使用されます。メトリクスでは、コード内の #pragma pack 指令も考慮されます。

すべて展開する

int flag();

int func(int param) {
  int var_1;
  int var_2;
  if (flag()) {
      int var_3;
      int var_4;
    } else {
      int var_5;
    }
}

この例では、int が 4 バイトと仮定すると、ローカル変数サイズの小さいほうの推定値は 24 になります。メトリクスの内訳を次の表に示します。

変数サイズ (バイト単位) 累積合計
戻り値4 4
パラメーター param48
ローカル変数 var_1var_24+4=816
if 条件で定義されるローカル変数

max(4+4,4)= 8

最初の分岐における変数のサイズは 8 バイトです。2 つ目の分岐のサイズは 4 バイトです。2 つの分岐の最大値は 8 バイトです。

24

関係するすべての変数が同じ型であるため、メモリ アライメントにはパディングが導入されません。

char func(char param) {
  int var_1;
  char var_2;
  double var_3;
}

この例では、char が 1 バイト、int が 4 バイト、double が 8 バイト、アライメントが 4 バイトと仮定すると、ローカル変数のサイズの小さいほうの推定値は 20 になります。使用しているプラットフォームでのアライメントは、通常ワード サイズです。Polyspace プロジェクトでは、ターゲット プロセッサを使ってアライメントを指定します。詳細は、ターゲット プロセッサ タイプ (-target)の [アライメント] 列を参照してください。

サイズの詳細を次の表に示します。

変数サイズ (バイト単位) 累積合計
戻り値1 1
param が保存される前に導入される追加パティング

0

次の変数 param が同じサイズであるため、メモリ アライメントは必要ありません。

1
パラメーター param12
var_1 が保存される前に導入される追加パティング

2

次の変数 var_1 には 4 バイトが必要になるため、パディングを使用してメモリ アライメントを行わなければなりません。ストレージは、4 の倍数のメモリ アドレスから始まらなければなりません。

4
var_148
var_2 が保存される前に導入される追加パティング

0

次の変数 var_2 のサイズが小さいため、メモリ アライメントは必要ありません。

8
var_219
var_3 が保存される前に導入される追加パティング

3

次の変数 var_3 には 8 バイトが必要なため、パディングを使用してメモリを調整する必要があります。ストレージは、4 バイトの倍数でアライメントされたメモリ アドレスか始まらなければなりません。

12
var_3820

パディング量に関するルールは以下のとおりです。

  • 保存される次の変数のサイズが同じか小さい場合、パディングは必要ありません。

  • 次の変数のサイズが大きい場合は以下のとおりです。

    • 変数サイズがプラットフォームのアライメントよりも小さいか同じの場合、ストレージ アドレスがそのサイズの倍数になるように、十分な量のパディングを行わなければなりません。

    • 変数サイズがプラットフォームのアライメントより大きい場合は、ストレージ アドレスがアライメントの倍数になるように、十分な量のパディングを行わなければなりません。

class MySimpleClass {
  public:

    MySimpleClass() {};

    MySimpleClass(int) {};

    ~MySimpleClass() {};  
};


int main() {
  MySimpleClass c;
  return 0;
}

この例では、ローカル変数の推定サイズは以下です。

  • コンストラクター MySimpleClass::MySimpleClass():4 バイト。

    このサイズは this ポインターに由来します。これは、コンストラクターの暗黙的な引数です。オプションターゲット プロセッサ タイプ (-target)を使用してポインター サイズを指定します。

  • コンストラクター MySimpleClass::MySimpleClass(int):8 バイト。

    このサイズは this ポインターと int 引数に由来します。

  • デストラクター MySimpleClass::~MySimpleClass():4 バイト。

    このサイズは this ポインターに由来します。

  • main():5 バイト。

    このサイズは int 戻り値とオブジェクト c のサイズに由来します。オブジェクトの最小サイズは、オプションターゲット プロセッサ タイプ (-target)を使用して指定するアライメントです。

class MyClass {
  public:
    MyClass() {};
    MyClass(int) {};
    ~MyClass() {};
  private:
    int i[10];   
};
void func1(const MyClass& c) {
}


void func2() {
  func1(4);  
}

この例では、func2() のローカル変数の推定サイズは 0 です。func2() によって func1() が呼び出されると、クラス MyClass の一時オブジェクトが作成されます。一時変数は計算から除外されます。func2 の本体で明示的に宣言されている変数はないため、報告されるメトリクスの値は 0 です。

class WrapperA {
private:
	int       start;
	int       end;
public:

	virtual int get_start() {
		return start;
	}
};


WrapperA aG;

WrapperA get_WrapperA_1() {
	//...
	return aG;
}


WrapperA  get_WrapperA_2() {
	//...
	WrapperA bL;
	return bL;
}


int main(){
	return 1;
}

この例では、関数の get_WrapperA_1get_WrapperA_2 がクラス WrapperA のオブジェクトを返します。get_WrapperA_1 の推定値が aG のサイズと等しくなると予想するかもしれません。戻り値の型の最適化後は、get_wrapperA_1()aG のコピーを指す WrapperA* ポインター型が含まれます。get_wrapperA_1() のローカル変数サイズの小さいほうの推定値は 4 バイトです。

同様に、戻り値の型の最適化後は、get_WrapperA_2WrapperA オブジェクトと WrapperA* ポインターが含まれます。get_wrapperA_2() のローカル変数のサイズの小さいほうの推定値は 16 バイトです。

メトリクス情報

グループ: 関数
頭字語: LOCAL_VARS_MIN
HIS メトリクス:いいえ

バージョン履歴

R2016b で導入

すべて展開する