【问题标题】:Can you know your max stack depth after you compile?编译后你能知道你的最大堆栈深度吗?
【发布时间】:2014-06-19 09:43:45
【问题描述】:

有没有办法在 linux 环境中轻松监控堆栈深度?

考虑在 Ubuntu 中使用 gcc 编译的 C 基本应用程序。

如果您不允许动态内存分配(没有 malloc/free-ing)怎么办?

【问题讨论】:

标签: c linux stack


【解决方案1】:

编译后你能知道你的最大堆栈深度吗?

否。考虑一个递归函数,它可能会根据输入多次调用自身。在不知道程序的输入是什么的情况下,您无法知道该函数可能被调用多少次,一次在最后一次。

我希望可以确定一些程序的最大堆栈深度,但您无法确定所有程序的最大堆栈深度。

有没有办法在 linux 环境中轻松监控堆栈深度?

我不知道有什么简单的方法可以连续监控堆栈深度,但是您可以使用 gdb 的 -stack-info-depth 命令随时确定堆栈深度。

如果你不允许动态内存分配(没有 malloc/free-ing)怎么办?

这并没有什么不同。考虑一个递归斐波那契函数——它不需要动态分配任何内存,但堆栈帧的数量仍然会根据输入而变化。

【讨论】:

  • 动态内存分配没有区别,因为它不从堆栈分配内存。与递归函数无关。
  • 如果您的程序中没有任何递归调用怎么办?这是否足以限制您可以知道最大堆栈深度的情况?
  • @lurker 我同意。递归函数只是一个很好的例子,说明了为什么在编译时无法确定堆栈深度。只需考虑一个函数,就很容易看出堆栈深度如何仅根据输入而变化。而fib() 是一个简单的、广为人知的示例,它不动态分配任何内存。
  • @Caleb 是的,我明白你的意思,我同意。
  • @tarabyte 再次,不。考虑两个函数a()b(),其中a 调用bb 调用a。确切地说,它们不是递归,但堆栈深度仍会根据编译时未知的条件而变化。接下来,考虑组中可能有 30 或 40 个函数,而不是 2 个函数。只有确定调用图中没有 个循环,才能确定最大堆栈深度。
【解决方案2】:

可以进行调用图分析。图中最长的路径是最大堆栈深度。但是,有一些限制。

对于递归函数,所有的赌注都没有,递归的深度取决于运行时输入,在编译时分析中不可能推断出来。 [可以通过分析调用图并寻找自身边,即具有相同源和目的地的边来检测递归函数的存在。]

此外,如果调用图中存在循环/循环,也会出现同样的问题。 [正如@Caleb 提到的:a()->b()->c()->d()->e()->f()->g()->c()] [使用图论算法,也可以检测循环的存在。]

调用图参考:

【讨论】:

  • 不仅递归函数无法确定堆栈深度,还有调用图中的 any 循环。也就是说,不仅需要考虑“自边缘”,还需要考虑像 a()->b()->c()->d()->e()->f()->g()->c() 这样的循环。
  • @Caleb:好点子,谢谢,我已经根据您的意见更新了答案。
  • 如果调用图分析返回“无循环”,我可以知道最大堆栈深度吗?足够公平的限制吗?
  • 只要您不进行不透明的 lib 调用,或者在某些操作系统上,不进行系统调用并确保您不被中断,那么也许...
猜你喜欢
  • 1970-01-01
  • 2015-08-13
  • 2015-12-17
  • 1970-01-01
  • 2014-06-25
  • 2012-10-13
  • 1970-01-01
  • 2011-05-29
  • 2021-08-09
相关资源
最近更新 更多