如何在堆栈中找到最大变量数

时间:2014-10-16 10:16:37

标签: c callstack

在执行以下程序期间,堆栈中一段时间​​内绑定的最大变量数是多少:

int x, y, z;

int g(int a, int b) {
  int c = 5 * a + b;
  return c;
}

int f(int a, int b) {
  a = g(a, 5);
  return g(b, a);
}

int main() {
  int a, b, c;
  x = y = z = 0;
  a = 5; b = 6;
  c = f(a, b);
  printf("%d", c);
}

如果有人知道如何找到它,请。你能解释一下我要做什么,以便在每个可能给出的代码中找到它。  没有任何优化。

另一个例子:

int x,y;

int f(int a){
  if (a!=5)
    return f(--a);
  else 
    return a;
}

int main(){
  int a,b;
  a=8;b=6;
  x=f(a);
  y=f(b);
  printf("%d", x+y);

  return 0;
}

这是否高于答案6?因为第一次返回,返回一个变量3次..而第二次返回一次返回一个数字,我们在main中有两个变量那么6?

2 个答案:

答案 0 :(得分:2)

您可以在脑中(或在调试器中)逐步运行程序,并可以计算call stack每个帧中的所有活动变量(然后获得它们的最大总和)。

在您的特定示例中,假设没有优化,最深的调用堆栈发生在由return c;调用的g调用的f main语句中。所以我们有3个调用堆栈帧,其中3个变量用于gabc;我假设形式类似于局部变量,这并非总是如此在实践中!),f的两个变量(ab)和main的3个变量。

您的老师可能希望您在最深的状态下绘制调用堆栈。我把它留给你。

实际上,有几个变量不占用任何堆栈空间,例如:因为它们位于寄存器中,或与另一个变量共享一个堆栈槽。这是编译器和ABI以及处理器架构和操作系统特定的。

然而,作为Ilya answered,一个好的编译器会改变你的optimization purposes程序,所以在实践中答案可能会有所不同。

如果使用GCC,您可能会尝试查看生成的汇编程序代码(使用gcc -fverbose-asm -S),您将看到结果和使用的变量数量取决于优化标记(即-O1-O2等等......或者缺少它们。您还可以使用GCC特定的-fstack-usage标志。您甚至可以尝试-fdump-tree-all标记到gcc,它会提供数百个转储文件,详细说明编译器中程序的各种中间表示(Gimple,SSA,...)。

另请阅读continuations(也可能是call/cc),tail callrecursioninline expansion上的wikipages。

BTW,调用堆栈的存在并不是C99标准所要求的严格意义(但我知道没有使用任何调用堆栈的C的实现)。如果你很好奇,你应该阅读A.Appel的旧论文garbage collection can be faster than stack allocation(它解释了SML不使用任何调用堆栈的实现,因为它正在分配每个“调用帧”,即“延续帧” ,在垃圾收集堆中。)

我还建议您编译示例(使用gcc -Wall -g),然后在gdb调试器中逐步运行 。经常使用display的{​​{1}},stepbacktraceframe commands

答案 1 :(得分:1)

这取决于编译器和优化设置。好的优化算法会生成这样的东西:

int main() {
  printf("%d", 155);
}

其他算法会生成其他内容。因此,尝试使用反汇编程序来编译结果。