2

8ビットAVRマイクロコントローラーのプログラミング私はこのコードに示されている振る舞いに出くわしました:

  class classA
  {
      public:
          classA(Display *d) : _d(d) { _d->println("classA()", 0); }
          ~classA() { _d->println("~classA()", 1); }
          uint8_t array[200];
          Display *_d;
  };
  void useClassA(classA *a)
  {
      a->array[3] = 5;
  }
  void SomeClass::start()
  {
      SYSTEM_DISPLAY_FREE_RAM();
      debugMethod();
      _ui->lcd().println("after debugMethod", 3);
      SYSTEM_WAIT_DEBUG_BUTTON();
      SYSTEM_DISPLAY_FREE_RAM();
  }
  void SomeClass::debugMethod()
  {
      _ui->lcd().println("entered debugMethod", 3);
      SYSTEM_WAIT_DEBUG_BUTTON();
      SYSTEM_DISPLAY_FREE_RAM();

      _ui->lcd().println("before while", 3);
      SYSTEM_WAIT_DEBUG_BUTTON();
      volatile uint8_t i = 1;
      while (i != 0) 
      {
          classA cA(&_ui->lcd());
          SYSTEM_DISPLAY_FREE_RAM();
          cA.array[199] = i--;
          useClassA(&cA);
      }
      _ui->lcd().println("after while", 3);
      SYSTEM_WAIT_DEBUG_BUTTON();
      SYSTEM_DISPLAY_FREE_RAM();
  }

SYSTEM_DISPLAY_FREE_RAM()は、http://jeelabs.org/2011/05/22/atmega-memory-use/で説明されているように、使用可能なRAMを計算し ます。実行がSomeClass::start()に達すると、次の出力が得られました。

  Free Ram: 2677
  entered debugMethod
  Free Ram: 2458
  before while
  classA()
  Free Ram: 2458
  ~classA()
  after while
  Free Ram: 2458
  after debugMethod
  Free Ram: 2677

オブジェクトclassAは、の内部で作成および破棄されますがwhile、メモリはの開始時に割り当てられているようでありdebugMethod()、メソッドが終了するまで残ります。私は、メモリがしばらくの間だけ割り当てられることを期待していたので、Free Ram: 2458

何が起こっているのかについての説明はありますか?

キーワードwhileを使用せずに、の内部で割り当てを強制的に実行する方法はありますか?new

使用したコンパイラ:avr-gcc(WinAVR 20100110)4.3.3

4

1 に答える 1

4

通常、関数全体のスタックフレームは、関数の開始時に割り当てられます。--param min-pretend-dynamic-size=100 100バイトを超えるオブジェクトのスタックを動的に割り当ておよび割り当て解除しようとするgcc引数を試すことができます[1]。

gccは、-Sスイッチを使用してアセンブリコードを表示し、それを見て、何が起こっているのか、そして--parammin-pretend-dynamic-sizeがプラットフォームと機能に影響を与えたかどうかを確認できます。

この場合の別の解決策は、while()ループの本体を新しい関数に移動することです。これにより、classAオブジェクトを含むスタックフレームが作成/破棄されます。

[1] gccドキュメント:

min-pretend-dynamic-size

バイト単位のサイズが指定された値以上の自動オブジェクトを、コンパイル時にサイズがわからないかのように動的に割り当てるように強制します。これにより、それらを含むブロックの最後でストレージを解放できるようになり、スタックの使用量が多い複数の関数が1つの関数にインライン化される場合に、スタックの合計使用量が削減されます。レジスタへの割り当てに適したオブジェクト(つまり、十分に小さく、アドレスが取得されていないオブジェクト)にも、関数の最も外側のブロックに割り当てられたオブジェクトにも影響はありません。デフォルトのゼロは、コンパイル時にサイズがわかっているオブジェクトに、関数のエントリでストレージが割り当てられるようにします。

于 2012-08-30T13:42:43.033 に答える