Memory 如何确定最大堆栈使用率?

Memory 如何确定最大堆栈使用率?,memory,embedded,stack,code-analysis,Memory,Embedded,Stack,Code Analysis,有哪些方法可用于确定嵌入式/内存受限系统的最佳堆栈大小?如果它太大,那么内存就会被浪费,而这些内存本可以用在其他地方。然而,如果它太小,那么我们得到这个网站的同名 要想快速开始工作:杰克·甘斯勒(Jack Ganssle)在书中说,“凭经验,人们可以学会计算堆栈正确大小的标准、科学方法:随机选择一个大小,然后满怀希望。”还有谁能做得更好吗 要求提供更具体的例子。那么,一个C程序在没有操作系统的情况下,使用工具链,以一个内存为2kB的内存为目标,怎么样?此IDE可以在使用JTAG调试器时显示堆栈内

有哪些方法可用于确定嵌入式/内存受限系统的最佳堆栈大小?如果它太大,那么内存就会被浪费,而这些内存本可以用在其他地方。然而,如果它太小,那么我们得到这个网站的同名

要想快速开始工作:杰克·甘斯勒(Jack Ganssle)在书中说,“凭经验,人们可以学会计算堆栈正确大小的标准、科学方法:随机选择一个大小,然后满怀希望。”还有谁能做得更好吗


要求提供更具体的例子。那么,一个C程序在没有操作系统的情况下,使用工具链,以一个内存为2kB的内存为目标,怎么样?此IDE可以在使用JTAG调试器时显示堆栈内容和用法。

您使用静态分析标记了问题,但这是一个很难通过静态分析解决的问题。堆栈的使用取决于程序的运行时配置文件,特别是在使用递归或alloca时。考虑到这是一个嵌入式平台,我想运行ps或top之类的东西并查看应用程序使用了多少堆栈也很困难

一种有趣的方法是使用当前堆栈帧的地址来确定使用了多少堆栈。您可以通过获取函数参数或局部变量的地址来实现这一点。对主函数和您认为使用最多堆栈的函数执行此操作。差异将告诉您应用程序需要的堆栈数量。下面是一个示例(假设通常的堆栈从高到低增长)

如果编译器允许您指定自定义函数序言(许多这样做是为了允许基于图形的程序评测),那么您甚至可以安排所有函数调用此类代码。那么你的测量函数是这样的

void
stack_measurement_function(void)
{
    int a;
    stack_bottom = min(stack_bottom, (char *)&a);
    // ...
}

我使用了一种类似于我所描述的生成方法。

确定最深堆栈使用量的最常用方法是使用一些已知但不寻常的值初始化堆栈内存,然后定期(或在大型测试运行结束时)查看该模式停止的位置


这正是IAR IDE确定堆栈使用量的方式。

使用良好的源代码静态分析工具,您可以为应用程序生成调用图。考虑到这一点,以及编译器生成的局部变量/临时变量的数量估计,您可以直接计算堆栈需求的保守估计

我所说的“好的”分析工具是一种可以读取所有涉及的编译单元,可以确定直接函数调用,可以确定间接指针,在编译单元中,可以计算整个系统的保守分析点,可以在考虑分析点的情况下构建调用图的工具。这就消除了很多工具,这就是为什么人们会看到特别的方法,比如“在运行时填充堆栈,看看会发生什么”。您还需要估计编译器放置在堆栈上的堆栈需求;您只需知道所有类型的存储需求有多大,就可以大致了解这一点,这对于嵌入式系统C程序来说通常相当容易确定。最后,您需要相信您的应用程序没有递归调用,或者该工具有最深层递归的概念(可能是通过您告诉它)

DMS软件再工程工具包满足C程序的所有这些要求。 看见 您仍然需要对其进行配置,通过对调用图进行爬网并使用各种大小估计来计算堆栈需求

如果您想要快速回答,请使用堆栈填充技巧。如果您想要在每次源代码更改后重新计算的答案,则需要静态分析方法。

  • 永远不要使用递归或递归算法。(注意正则表达式库)
  • 不要使用数组,始终使用malloc()
  • 不要使用alloca(),有些编译器甚至在这个函数中有bug
然后手工检查代码部分,寻找堆栈使用率最高的地方(记得我说过没有数组)

  • 检查代码本身中可疑的高点处的堆栈使用情况,记录到调试器界面
  • 根据估计的堆栈使用情况放置封盖,并将封盖放置到位。e、 g.限制服务器连接

我现在正在研究这个问题,即堆栈大小的分析计算。 这显然将是一段高度递归的代码,因为函数调用可能有一个索引数组作为其一个或多个参数,并且一个或多个数组索引可能涉及函数调用

但是,有两种实现方式可以在一定程度上缓解复杂性:

(1) 使用高级语言编译器时,每个语句/代码行执行结束时的堆栈指针应与开始时的位置相同。 (至少这是一个很好的遵守规则,否则你会有问题!)

(2) 从每个函数或子例程调用返回后的堆栈指针应与调用前的堆栈指针相同。因此,最大堆栈大小是程序中所有语句中每个语句达到的峰值堆栈大小的最大值。 (至少这是一个很好的遵守规则,否则你会有问题!)

当然,一条语句可以包含我上面提到的递归问题,但至少查找整个程序的最大stacksize需求的问题可以归结为查找每条语句的最大stacksize需求,然后选择其中的最大值

在所有调用的函数也被编译之前,无法完成此操作。因此,我为每个编译的模块生成一个文件,记录每个语句的堆栈大小 (基本上是每个函数调用之前的峰值和每个函数调用之前的中间值(不包括任何函数调用)
void
stack_measurement_function(void)
{
    int a;
    stack_bottom = min(stack_bottom, (char *)&a);
    // ...
}