处理嵌入式系统中的堆栈溢出

8 stack-overflow embedded error-handling

在嵌入式软件中,如何以通用方式处理堆栈溢出?我遇到了一些处理器,它像硬件一样保护最近的AMD处理器.维基百科上有一些技术,但那些是真正实用的方法吗?

任何人都可以提供一个明确的建议方法,适用于当今的32位嵌入式处理器吗?

Cra*_*een 12

理想情况下,您使用静态堆栈使用编写代码(没有递归调用).然后,您可以评估最大堆栈使用情况:

  1. 静态分析(使用工具)
  2. 在运行代码时测量堆栈使用情况,同时使用完整的代码覆盖率(或者尽可能高的代码覆盖率,直到您有合理的信心确定堆栈使用的程度,只要您很少运行的代码不使用更多堆栈比正常执行路径)

但即便如此,您仍然希望有一种检测并随后处理堆栈溢出的方法(如果可能的话),以获得更高的稳健性.这在项目开发阶段尤其有用.一些检测溢出的方法:

  1. 如果处理器支持存储器读/写中断(即存储器访问断点中断),则可以将其配置为指向堆栈区域的最远范围.
  2. 在内存映射配置中,设置一个小的(或大的)RAM块,它是一个"堆栈保护"区域.用已知值填充它.在嵌入式软件中,定期(尽可能经常)检查该区域的内容.如果它发生变化,则假设堆栈溢出.

一旦你检测到它,那么你需要处理它.我不知道代码可以从堆栈溢出中优雅地恢复的许多方法,因为一旦发生这种情况,您的程序逻辑几乎肯定会失效.所以你所能做的就是

  1. 记录错误
    1. 记录错误非常有用,因为否则症状(意外重新启动)可能很难诊断.
    2. 警告:即使在损坏的堆栈场景中,日志记录例程也必须能够可靠地运行.例程应该简单.即使堆栈损坏,您可能无法尝试使用花哨的EEPROM写入后台任务写入EEPROM.也许只需将错误记录到为此目的而保留的结构中,在非初始化RAM中,然后可以在重新启动后进行检查.
  2. 重启(或者可能是关机,尤其是重复出错的情况)
    1. 可能的替代方法:仅重新启动特定任务,如果您正在使用RTOS,并且您的系统设计为隔离堆栈损坏,并且所有其他任务都能够处理该任务重新启动.这需要一些严肃的设计考虑.


Sea*_*ney 1

发生堆栈溢出,堆栈内存因调用堆栈太大而耗尽?例如,递归函数的深度过多。

有一些技术可以通过将已知数据放置在堆栈后面来检测堆栈溢出,这样就可以检测堆栈是否增长过多并覆盖它。

有一些静态源代码分析工具,例如 GnatStack、AbsInt 的 StackAnalyzer 和 Bound-T,它们可用于确定或猜测最大运行时堆栈大小。