我现在正在解决这个问题 - 即堆栈大小的分析计算。这显然将是一段高度递归的代码,因为函数调用可以将索引数组作为其一个或多个参数,并且一个或多个数组索引可能涉及函数调用!
然而,一些实现可以从复杂性中解脱出来:
(1) 使用高级语言编译器时,每条语句/代码行执行结束时的堆栈指针应与开始时的位置相同。(至少这是一个很好的规则,否则你会遇到问题!)
(2)每个函数或子程序调用返回后的堆栈指针应与调用前相同。因此,最大堆栈大小是程序中所有语句中每个语句达到的峰值堆栈大小的最大值。(至少这是一个很好的规则,否则你会遇到问题!)
当然,一条语句可以包含我上面提到的递归问题,但至少找到整个程序的最大堆栈大小要求的问题归结为找到每个语句的最大堆栈大小要求,然后选择其中的最大值。
在所有调用的函数也都被编译之前,这无法完成。因此,我为每个编译的模块生成一个文件,记录每个语句的堆栈大小(基本上是每个函数调用之前的峰值和每个函数调用之前的值(不包括由函数引起的任何未知的堆栈大小添加) call) 以及所涉及的函数名称。然后,一旦编译了所有函数,我就使用递归例程回顾性地处理这些文件,以确定峰值堆栈大小。
幸运的是,除了递归例程之外,最大可能的堆栈大小要求并不取决于程序流,尽管在典型的流(取决于数据)中,可能永远不会达到最大可能的堆栈大小。
示例:假设函数 1 调用函数 2,并且两者的程序流程都依赖于数据值 X。假设有一个 X 范围导致函数 1 执行其最差的语句,其中包括对函数 2 的调用,该语句不执行对于相同范围的 X,它是最坏情况的陈述。由于我们同时使用函数 1 和函数 2 的最坏情况来计算最大可能的堆栈大小,因此我们可能高估了堆栈大小。至少我们在安全方面犯了错误。
如果需要,我喜欢在 OS 堆栈上为中断例程提供自己的堆栈空间,因此它们不会增加程序堆栈要求,除了从中断返回的地址