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() 计算可用 RAM,如 http://jeelabs.org/2011/05/22/atmega-memory-use/中所述。当执行到达 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

通常,整个函数的堆栈帧是在函数开始时分配的。您可以尝试 gcc 参数,该参数--param min-pretend-dynamic-size=100 将尝试为超过 100 字节的对象动态分配和释放堆栈 [1]。

gcc 可以向您显示带有-S开关的汇编代码,查看它以了解正在发生的事情,以及 --param min-pretend-dynamic-size 是否对您的平台和功能有任何影响。

在您的情况下,另一个解决方案是将 while() 循环的主体移动到一个新函数中,因为这将创建/销毁包含 classA 对象的堆栈框架。

[1] gcc 文档:

最小假装动态大小

强制任何以字节为单位的大小等于或大于指定值的自动对象被动态分配,就好像它们的大小在编译时是未知的。这使得它们的存储能够在包含它们的块的末尾被释放,如果多个使用大量堆栈的函数被内联到一个函数中,则可以减少总堆栈使用量。它不会对适合分配给寄存器的对象产生任何影响(即,足够小并且没有占用其地址的对象),也不会对分配在函数最外层块中的对象产生任何影响。默认值为零,导致其大小在编译时已知的对象在函数入口处分配存储空间。

于 2012-08-30T13:42:43.033 回答