【问题标题】:How will I know when my memory is full?我怎么知道我的内存是满的?
【发布时间】:2011-05-07 18:28:48
【问题描述】:

我正在用 c 语言为 Atmel XMEGA 微控制器编写固件,我想我填满了 4 KB 的 SRAM。据我所知,我只有静态/全局数据和本地堆栈变量(我在我的代码中使用 malloc)。

我使用一个局部变量来缓冲一些像素数据。如果我将缓冲区增加到 51 字节,我的显示器会显示奇怪的结果 - 6 字节的缓冲区运行良好。这就是为什么我认为我的 ram 已满并且堆栈正在覆盖某些内容。

创建更多可用内存不是我的问题,因为我可以将一些静态数据移动到闪存中,并且只在需要时加载它。令我困扰的是,我从来没有发现内存已满。

当内存被填满而不是让它覆盖一些其他数据时,是否可以通过某种方式检测(例如通过重置微控制器)?

【问题讨论】:

    标签: c memory stack stack-overflow microcontroller


    【解决方案1】:

    很难准确预测您需要多少堆栈(如果您打开正确的选项,一些工具链可以尝试这样做,但这只是一个粗略的指南)。

    检查堆栈状态的一种常见方法是在启动时用已知值完全填充它,尽可能长时间地运行代码,然后查看有多少没有被覆盖。

    您的工具链的启动代码甚至可以选择为您填充堆栈。

    不幸的是,尽管这些概念非常简单:用已知值填充堆栈,计算剩余值的数量,实现它的现实可能需要对您的特定工具(尤其是启动代码和链接器)工作。

    检查堆栈溢出是否导致问题的粗略方法是使所有本地数组“静态”和/或极大地增加堆栈的大小,然后看看事情是否更好。这些在小型嵌入式系统上都很难做到。

    【讨论】:

      【解决方案2】:

      “是否有可能检测到(例如 通过复位微控制器)时 内存被填满而不是 让它覆盖其他一些数据?”

      我想目前你有一个像 (1) 这样的内存映射。 当堆栈和/或变量空间增长到很多时,它们会发生冲突并相互覆盖 (*)。

      另一种可能性是像 (2) 这样的内存映射。 当堆栈或变量空间超过最大空间时,它们会命中未映射的地址空间 (*)。 根据控制器(我不确定 AVR 系列),这会导致重置/陷阱或类似情况(=您想要的)。

        [not mapped addr space][   RAM  mapped  addr  space   ][not mapped addr space] 
      (1)                      [variables --->  *   <--- stack] 
      (2)                     *[ <--- stack   variables --->  ]* 
      

      (如果使用更多变量/堆栈,箭头表示增长方向)

      当然最好事先确保 RAM 足够大。

      【讨论】:

        【解决方案3】:

        通常,链接器负责为代码、常量、静态数据、堆栈和堆分配内存。通常,您必须为链接器指定所需的堆栈大小(和可用内存),如果它无法容纳所有内容,则会标记错误。

        另请注意,如果您正在处理多线程应用程序,那么每个线程都有自己的堆栈,并且这些堆栈通常在线程启动时从堆中分配。

        除非您的处理器有一些硬件检查堆栈溢出(不太可能),否则您可以使用一些技巧来监控堆栈使用情况。

        • 用已知的标记模式填充堆栈,并检查堆栈内存(由链接器分配)以确定有多少标记仍未损坏。
        • 在定时器中断(或类似中断)中,将主线程堆栈指针与堆栈底部进行比较以检查是否溢出

        这两种方法在调试中都很有用,但它们不能保证捕捉到所有问题,并且通常只会在堆栈已经损坏其他东西之后才标记问题...

        【讨论】:

          【解决方案4】:

          通常你的编程工具知道控制器的参数,所以如果你使用更多应该警告你(没有malloc,在编译时就知道了)。

          但是你应该小心像素数据,因为大多数显示器没有线性地址空间。

          编辑:通常您可以手动指定堆栈大小。为静态变量留出足够的内存,其余的留给堆栈。

          【讨论】:

          • 据我所知,局部变量确实存在于堆栈中。但是堆栈的大小在编译时是未知的,还是我错了?
          • @Martin:如果您不使用递归和可变大小的局部变量,堆栈的大小可以在编译时知道(无论如何,只有某些 C 编译器允许使用字母)。
          猜你喜欢
          • 2011-08-30
          • 2017-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-24
          • 1970-01-01
          相关资源
          最近更新 更多