如何跟踪递归深度

How do I track recursion depth?

本文关键字:递归 深度 跟踪 何跟踪      更新时间:2023-10-16

我有一个递归函数,我正在排除故障。我想输出递归深度…函数调用自己的次数

如果我使用一个静态变量,在函数的顶部递增,在底部递减。

这能准确地给出深度等级吗?

recurse()
  {
  static int depth = 0;
  depth++;
  /*
  do stuff
  recurse()
  */
  depth--;
  return return_value;
  }
recurse(int depth = 0){
    ....
    recurse(depth+1);
}

为了方便,

  • 异常安全
  • 线程安全的
  • 支持树递归

<子>如果您真的发挥您的想象力,这可以使编译器更容易内联一些递归调用,和/或在尾部递归的情况下执行尾部调用优化。我没有证据表明这起作用,但我可以想象从函数体中引用外部符号会影响编译器优化。

我建议:

stuff recurse(int level=0)
{
     //...
     recurse(level+1);
     //... (return stuff?)
     //... (throw exceptions?)
     //...
     recurse(level+1);
     //... (return stuff?)
}

不,如果抛出异常,它可能不会。一个更好的(也是更常见的)选项是:

int recurse(int depth=0)
{
    recurse(depth+1)
    return return_value;
}

如果你想做这件非侵入性的事情,你可以让你的编译器为你检测每次调用,例如使用gcc:

#include <iostream>
static __thread int depth=-1;
extern "C" {
    void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));
    void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function));
    void __cyg_profile_func_enter (void *func,  void *caller)
    {
        depth++;
    }

    void __cyg_profile_func_exit (void *func, void *caller)
    {
        depth--;
    }
}
class Foo {
public:
    void bar() {
        std::cout << "bar: " << depth << std::endl;
    }
};
int main() {
    Foo f;
    f.bar();
    return 0;
}

您需要使用-finstrument-functions进行编译才能使其工作

出于线程安全的目的,通常需要增加在递归函数外部定义的深度变量,并从该函数外部打印它。

下面是一个简单的阶乘示例:

#include <stdio.h>
unsigned factorial(unsigned x, unsigned* depth)
{
  if (x <= 1)
    return 1;
  ++*depth;
  return x * factorial(x - 1, depth);
}
int main(void)
{
  unsigned depth, f;
  depth = 0; f = factorial(1, &depth);
  printf("factorial=%u, depth=%un", f, depth);
  depth = 0; f = factorial(2, &depth);
  printf("factorial=%u, depth=%un", f, depth);
  depth = 0; f = factorial(6, &depth);
  printf("factorial=%u, depth=%un", f, depth);
  return 0;
}
输出:

C:>recdep.exe
factorial=1, depth=0
factorial=2, depth=1
factorial=720, depth=5

在单线程上下文中可以工作。

是的,它应该工作。