为什么嵌入式系统需要堆栈分析?如何进行监控堆栈分析呢?

描述

随着代码行数从几千到上百万不等,嵌入式软件变得日益复杂,但总体目标依然是实现稳健、正确且快速执行的软件。快速执行的软件需要以最优方式管理可用的 CPU 和内存资源,这对内存空间(尤其是 RAM)有限的嵌入式系统来说不失为一项挑战。

为此,必须通过执行堆栈和堆分析对 RAM 的使用情况进行分析。开发人员手动估计堆栈和堆负载是一项艰巨的任务,即使对于小程序来说也是如此。如果估计不正确,则可能会导致堆栈溢出和未定义的行为。

因此,一些编码标准要求强制执行内存分配使用最佳实践,以避免不必要的开销。但是,堆栈仍是 RAM 的必要组成部分,需要得到优化利用。

为什么嵌入式系统需要堆栈分析?

当可用堆栈小于代码需求时,就会发生堆栈溢出。然而,当为环境配置的堆栈大于需求时,内存又会被浪费。开发人员必须持续一致地估计安全关键型应用中最差情形下的堆栈使用量,以防止软件运行时发生 RAM 不足的情况。

RAM

堆栈估计不正确所带来的风险。

如何估计堆栈分析?

手动估计堆栈

虽然手动估计堆栈分析偶尔会有帮助,但对于更复杂的系统来说可能充满挑战。这就需要彻底了解函数调用的深度、所有局部变量的细节,以及执行过程中随时发生的中断帧的大小,等等。这是一个漫长而又容易出错的过程。使用静态代码分析工具可以快速计算出上述结果,而不必手动执行这个过程。

使用静态代码分析器

开发人员可以通过静态代码分析器预测堆栈的使用情况。分析工具有助于分析函数调用深度、局部变量和返回参数的堆栈估计、嵌套中断以及执行期间发生的中断帧的大小。使用静态代码分析器的好处在于,它可以处理编码规则违规、运行时缺陷、编码复杂性以及堆栈分析估计。它在几分钟内就能完成这些操作,从而帮助开发人员节省了手动计算堆栈使用量的时间。

对目标进行测试和测量

静态分析器可以在开发过程中估计堆栈的使用量。但是,最好在真实硬件上获得实际的堆栈使用量数据。许多开发环境都具有硬件模拟功能,并提供实时堆栈分析功能。在实际硬件上执行堆栈分析,并创建溢出场景来测试故障安全例程,这一点非常重要。现在,最大的问题是:何时使用静态分析工具执行堆栈分析?何时在实际目标上执行?

何时执行堆栈分析?

执行堆栈分析是软件开发生命周期中的一个连续过程。如果仅在软件开发生命周期结束时由单独的质量评估团队估计堆栈使用量,则可能会使整个开发工作面临风险。此外,在开发周期的后期解决问题可能会出错且耗时;在确定是更改硬件还是软件设计时,这种做法可能还会造成混乱。执行堆栈分析的最佳时点是:

在添加新功能时

在软件中每添加一项新功能,都会使堆栈使用量增加。开发人员必须密切关注新功能的堆栈使用情况。

执行堆栈分析、进行调试和修复复杂代码:在每个主要功能实现后,开发人员可以在本地对特定软件组件或软件模块应用静态分析器,以评估基础软件和已实现软件之间堆栈使用量的增加情况。

在整个开发过程中监控堆栈分析:QA 团队和产品负责人可以使用静态分析器对持续集成 (CI) 管道进行堆栈估计,以在控制板上显示结果。此过程有助于在软件开发生命周期中跟踪堆栈分析。

执行良好实践以确保堆栈使用量最低:质量门有助于避免违反 MISRA 和 AUTOSAR 编码规范。这些规范要求强制有条件地使用动态内存分配。

在软件发布前

静态分析器执行的堆栈估计提供了有力的证据,表明堆栈使用量处于控制之中。在每次软件发布之前,都应在标准工作负载、最小负载和最大负载下,对真实目标运行堆栈分析,以全面了解堆栈的使用情况。验证堆栈上溢和下溢事件的故障安全例程也至关重要。

Polyspace 对堆栈估计有何作用?

Polyspace Code Prover 对每个函数中局部变量的大小上限和下限执行保守和乐观估计,以得出函数级和程序级的最大和最小堆栈使用量。该分析考虑了函数返回值的大小、函数参数的大小、局部变量的大小,以及内存对齐所需的额外填充。

RAM

Polyspace 桌面版上的堆栈分析代码度量。

要了解和调试堆栈利用过量的问题,开发人员可以在本地运行 Polyspace,通过检查函数调用深度来确定堆栈利用过量的确切原因,并通过优化利用可用资源来降低堆栈使用量。

RAM

函数 table_loop() 的调用树和更高的堆栈估计。

在整个开发过程中监控堆栈分析

Polyspace Access 是结果数据库服务器,可以在 Web 浏览器上呈现图形用户界面。CI 流程可以触发 Polyspace Server 上的堆栈分析,以生成堆栈使用量估计结果。此结果可以上传到结果数据库。QA 团队和产品负责人可以在图形化前端持续查看堆栈使用量,并在可用堆栈资源过度使用的情况下采取必要的措施。

RAM

Polyspace Access 中的项目级堆栈估计。

下一步是,检查堆栈使用量较高的函数,并将特定函数分配给开发人员,以供进一步调查和调试。Polyspace 允许您为分析结果指定状态和严重性并添加注释,然后在 Jira 等 Bug 跟踪工具中将这些结果分配给开发人员。

RAM

Polyspace Access 中的函数级堆栈估计和结果审查控制板。

执行良好实践以确保堆栈使用量最低

对于产品级代码,必须绝对避免违反编码标准,如 MISRA C、MISRA C++、AUTOSAR C++ 等。这些编码标准要求强制禁止动态内存分配,并推荐特定用例来优化静态内存分配。

Polyspace Bug Finder 有助于识别任何违反最佳实践的行为,开发人员可以在本地监控这些行为,而产品负责人可通过 Polyspace Access 监控这些行为。以下编码规则详细说明了静态内存分配的最佳实践。静态内存分配可以使用 Polyspace Bug Finder 进行分析。

RAM

随着代码的循环复杂度、嵌套函数调用的数量、函数中变量数目等的增加,堆栈的使用量也在增加。Polyspace 能够控制影响堆栈使用量的诸多变量,并支持设置代码复杂度阈值。

RAM

设置代码复杂度阈值。

Polyspace Bug Finder 提供了许多针对静态和动态内存分配的运行时检查。解决所有高、中和低优先级缺陷有助于降低内存分配带来的风险。

RAM

运行时静态和动态内存检查。

无论使用何种方法来计算堆栈使用量,稍微增大堆栈大小都不失为一个好办法。这种方法有助于避免测试期间可能未检测到的堆栈溢出导致的系统漏洞。

堆栈溢出漏洞是许多嵌入式应用程序在实际运行中表现出不可定义行为的一个重要原因。在正确的时间使用正确的工具并遵循最佳实践,可以增强对软件防止堆栈溢出的信心。



审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分